From 61af7f892a18e3354e399898acd61266a1820531 Mon Sep 17 00:00:00 2001 From: Ibraim Date: Tue, 28 Jul 2020 12:03:50 +0300 Subject: [PATCH] Upgrade 2020.1-1 --- .gitmodules | 3 + README.md | 4 +- hw/digilent-vivado-scripts/.gitignore | 12 + hw/digilent-vivado-scripts/License.txt | 21 + hw/digilent-vivado-scripts/README.md | 247 +++++++++ hw/digilent-vivado-scripts/config.ini | 6 + .../digilent_vivado_checkin.tcl | 220 ++++++++ .../digilent_vivado_checkout.tcl | 203 +++++++ hw/digilent-vivado-scripts/git_vivado.py | 207 +++++++ .../templates/README.md | 81 +++ .../templates/hw.gitignore | 53 ++ .../templates/project_info.tcl | 19 + hw/hw_handoff/.keep | 0 hw/proj/.keep | 0 hw/repo/cache/.keep | 0 hw/repo/local/.keep | 0 hw/src/bd/.keep | 0 hw/src/bd/user_35t.tcl | 508 ++++++++++++++++++ hw/src/constraints/.keep | 0 hw/src/hdl/.keep | 0 hw/src/ip/.keep | 0 hw/src/other/.keep | 0 project_info.tcl | 22 +- scripts | 1 + sw/scripts/LICENSE | 21 + sw/scripts/README.md | 61 +++ sw/scripts/checkin.tcl | 421 +++++++++++++++ sw/scripts/checkout.tcl | 102 ++++ sw/scripts/sub/build_app.tcl | 11 + sw/scripts/sub/cleanup._cmd | 24 + sw/scripts/sub/cleanup._sh | 14 + sw/scripts/sub/hw_pf_xsa.tcl | 15 + sw/scripts/sub/standalone_app.tcl | 39 ++ sw/scripts/sub/standalone_bsp.tcl | 18 + sw/scripts/sub/template.gitignore | 5 + sw/sdk/.keep | 0 sw/sdk/appsrc/intc/intc.c | 96 ++++ sw/sdk/appsrc/intc/intc.h | 75 +++ sw/sdk/appsrc/lscript.ld | 213 ++++++++ sw/sdk/appsrc/memory_config.h | 47 ++ sw/sdk/appsrc/memory_config_g.c | 10 + sw/sdk/appsrc/memorytest.c | 209 +++++++ sw/sdk/appsrc/platform.c | 94 ++++ sw/sdk/appsrc/platform.h | 41 ++ sw/sdk/appsrc/platform_config.h | 4 + sw/sdk/appsrc/userio/userio.c | 188 +++++++ sw/sdk/appsrc/userio/userio.h | 93 ++++ sw/src/Cmod-A7-35T-OOB/145_build_app.tcl | 11 + sw/src/Cmod-A7-35T-OOB/45_standalone_app.tcl | 51 ++ sw/src/Cmod-A7-35T-OOB/src/README.txt | 1 + sw/src/Cmod-A7-35T-OOB/src/intc/intc.c | 96 ++++ sw/src/Cmod-A7-35T-OOB/src/intc/intc.h | 75 +++ sw/src/Cmod-A7-35T-OOB/src/lscript.ld | 213 ++++++++ sw/src/Cmod-A7-35T-OOB/src/memory_config.h | 47 ++ sw/src/Cmod-A7-35T-OOB/src/memory_config_g.c | 10 + sw/src/Cmod-A7-35T-OOB/src/memorytest.c | 209 +++++++ sw/src/Cmod-A7-35T-OOB/src/platform.c | 94 ++++ sw/src/Cmod-A7-35T-OOB/src/platform.h | 41 ++ sw/src/Cmod-A7-35T-OOB/src/platform_config.h | 4 + sw/src/Cmod-A7-35T-OOB/src/userio/userio.c | 188 +++++++ sw/src/Cmod-A7-35T-OOB/src/userio/userio.h | 93 ++++ sw/src/README.md | 61 +++ sw/src/checkout.tcl | 102 ++++ .../domain_microblaze_0/25_standalone_bsp.tcl | 35 ++ sw/src/user_35t_wrapper/5_hw_pf_xsa.tcl | 20 + sw/src/user_35t_wrapper/user_35t_wrapper.xsa | Bin 0 -> 239384 bytes sw/ws/cleanup.cmd | 24 + sw/ws/cleanup.sh | 14 + 68 files changed, 4789 insertions(+), 8 deletions(-) create mode 100644 hw/digilent-vivado-scripts/.gitignore create mode 100644 hw/digilent-vivado-scripts/License.txt create mode 100644 hw/digilent-vivado-scripts/README.md create mode 100644 hw/digilent-vivado-scripts/config.ini create mode 100644 hw/digilent-vivado-scripts/digilent_vivado_checkin.tcl create mode 100644 hw/digilent-vivado-scripts/digilent_vivado_checkout.tcl create mode 100644 hw/digilent-vivado-scripts/git_vivado.py create mode 100644 hw/digilent-vivado-scripts/templates/README.md create mode 100644 hw/digilent-vivado-scripts/templates/hw.gitignore create mode 100644 hw/digilent-vivado-scripts/templates/project_info.tcl create mode 100644 hw/hw_handoff/.keep create mode 100644 hw/proj/.keep create mode 100644 hw/repo/cache/.keep create mode 100644 hw/repo/local/.keep create mode 100644 hw/src/bd/.keep create mode 100644 hw/src/bd/user_35t.tcl create mode 100644 hw/src/constraints/.keep create mode 100644 hw/src/hdl/.keep create mode 100644 hw/src/ip/.keep create mode 100644 hw/src/other/.keep create mode 160000 scripts create mode 100644 sw/scripts/LICENSE create mode 100644 sw/scripts/README.md create mode 100644 sw/scripts/checkin.tcl create mode 100644 sw/scripts/checkout.tcl create mode 100644 sw/scripts/sub/build_app.tcl create mode 100644 sw/scripts/sub/cleanup._cmd create mode 100644 sw/scripts/sub/cleanup._sh create mode 100644 sw/scripts/sub/hw_pf_xsa.tcl create mode 100644 sw/scripts/sub/standalone_app.tcl create mode 100644 sw/scripts/sub/standalone_bsp.tcl create mode 100644 sw/scripts/sub/template.gitignore create mode 100644 sw/sdk/.keep create mode 100644 sw/sdk/appsrc/intc/intc.c create mode 100644 sw/sdk/appsrc/intc/intc.h create mode 100644 sw/sdk/appsrc/lscript.ld create mode 100644 sw/sdk/appsrc/memory_config.h create mode 100644 sw/sdk/appsrc/memory_config_g.c create mode 100644 sw/sdk/appsrc/memorytest.c create mode 100644 sw/sdk/appsrc/platform.c create mode 100644 sw/sdk/appsrc/platform.h create mode 100644 sw/sdk/appsrc/platform_config.h create mode 100644 sw/sdk/appsrc/userio/userio.c create mode 100644 sw/sdk/appsrc/userio/userio.h create mode 100644 sw/src/Cmod-A7-35T-OOB/145_build_app.tcl create mode 100644 sw/src/Cmod-A7-35T-OOB/45_standalone_app.tcl create mode 100644 sw/src/Cmod-A7-35T-OOB/src/README.txt create mode 100644 sw/src/Cmod-A7-35T-OOB/src/intc/intc.c create mode 100644 sw/src/Cmod-A7-35T-OOB/src/intc/intc.h create mode 100644 sw/src/Cmod-A7-35T-OOB/src/lscript.ld create mode 100644 sw/src/Cmod-A7-35T-OOB/src/memory_config.h create mode 100644 sw/src/Cmod-A7-35T-OOB/src/memory_config_g.c create mode 100644 sw/src/Cmod-A7-35T-OOB/src/memorytest.c create mode 100644 sw/src/Cmod-A7-35T-OOB/src/platform.c create mode 100644 sw/src/Cmod-A7-35T-OOB/src/platform.h create mode 100644 sw/src/Cmod-A7-35T-OOB/src/platform_config.h create mode 100644 sw/src/Cmod-A7-35T-OOB/src/userio/userio.c create mode 100644 sw/src/Cmod-A7-35T-OOB/src/userio/userio.h create mode 100644 sw/src/README.md create mode 100644 sw/src/checkout.tcl create mode 100644 sw/src/domain_microblaze_0/25_standalone_bsp.tcl create mode 100644 sw/src/user_35t_wrapper/5_hw_pf_xsa.tcl create mode 100644 sw/src/user_35t_wrapper/user_35t_wrapper.xsa create mode 100644 sw/ws/cleanup.cmd create mode 100644 sw/ws/cleanup.sh diff --git a/.gitmodules b/.gitmodules index f00806c..79eb639 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "digilent-vivado-scripts"] path = digilent-vivado-scripts url = https://github.com/digilent/digilent-vivado-scripts.git +[submodule "scripts"] + path = scripts + url = https://github.com/Digilent/digilent-vitis-scripts diff --git a/README.md b/README.md index a54c12e..1bf1a75 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Whenever the demo is started from Vivado SDK, the board will go through a memory Requirements ------------ * **Cmod A7-35T**: To purchase a Cmod A7-35T, see the [Digilent Store](https://store.digilentinc.com/cmod-a7-breadboardable-artix-7-fpga-module/). -* **Vivado 2018.2 Installation with Xilinx SDK**: To set up Vivado, see the [Installing Vivado and Digilent Board Files Tutorial](https://reference.digilentinc.com/vivado/installing-vivado/start). +* **Vivado 2020.1 Installation with Xilinx SDK**: To set up Vivado, see the [Installing Vivado and Digilent Board Files Tutorial](https://reference.digilentinc.com/vivado/installing-vivado/start). * **Serial Terminal Emulator**: * **MicroUSB Cable** @@ -22,7 +22,7 @@ Demo Setup 1. Download the most recent release ZIP archive ("Cmod-A7-35T-OOB-2018.2-*.zip") from the repo's [releases page](https://github.com/Digilent/Cmod-A7-35T-OOB/releases). 2. Extract the downloaded ZIP. -3. Open the XPR project file, found at \/vivado_proj/Cmod-A7-35T-OOB.xpr, included in the extracted release archive in Vivado 2018.2. +3. Open the XPR project file, found at \/vivado_proj/Cmod-A7-35T-OOB.xpr, included in the extracted release archive in Vivado 2020.1. 4. In the toolbar at the top of the Vivado window, select **File -> Export -> Export Hardware**. Select **\** as the Exported Location and make sure that the **Include bitstream** box is checked, then click **OK**. 5. In the toolbar at the top of the Vivado window, select **File -> Launch SDK**. Select **\** as both the workspace location and exported location, then click **OK**. 6. With Vivado SDK opened, wait for the hardware platform exported by Vivado to be imported. diff --git a/hw/digilent-vivado-scripts/.gitignore b/hw/digilent-vivado-scripts/.gitignore new file mode 100644 index 0000000..272b872 --- /dev/null +++ b/hw/digilent-vivado-scripts/.gitignore @@ -0,0 +1,12 @@ +# Blacklist everything +/* + +# Whitelist this stuff +!License.txt +!config.ini +!*.tcl +!*.py +!*README.md +!*.gitignore +!templates +!templates/* \ No newline at end of file diff --git a/hw/digilent-vivado-scripts/License.txt b/hw/digilent-vivado-scripts/License.txt new file mode 100644 index 0000000..de71801 --- /dev/null +++ b/hw/digilent-vivado-scripts/License.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Digilent + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/hw/digilent-vivado-scripts/README.md b/hw/digilent-vivado-scripts/README.md new file mode 100644 index 0000000..2d86717 --- /dev/null +++ b/hw/digilent-vivado-scripts/README.md @@ -0,0 +1,247 @@ +# Digilent Vivado Scripts + +## Introduction +This repository contains a set of scripts for creating, maintaining, and releasing git repositories containing minimally version-controlled Vivado projects. A Python 3.6.3 (or newer) installation is required to use the Python frontend for these scripts. As of time of writing, no additional Python modules are depended on. + +---------------- +## Quick Guide + +This guide covers only what is required to gain access to and build demo project sources. For more in-depth details on these steps, and for information on how to push changes to a demo repository or build a release, see the **Workflows** section of this document, below. + +### Prerequisites +- You must have the URL for a demo repository that uses digilent-vivado-scripts as a submodule. + + For the purposes of this guide, any time that the text `` appears, you should replace it with the name of your chosen demo, as it appears at the end of the URL. For example, for the [Zybo Z7-20 HDMI demo](https://github.com/Digilent/Zybo-Z7-20-HDMI), `` should be replaced with `Zybo-Z7-20-HDMI`. +- Make sure that [Git](https://git-scm.com/) and a console application that can use it are installed on your computer. Most Linux systems will already have git installed. Windows users are recommended to use the Git Bash shell available through https://gitforwindows.org. +- Make sure you have the version of Vivado targeted by your chosen demo repository installed on your computer. The README for your chosen demo will describe which version of these tools it can be used with. Installation instructions can be found in the [Installing Vivado, Xilinx SDK, and Digilent Board Files](https://reference.digilentinc.com/vivado/installing-vivado/start) guide on the Digilent Wiki. FIXME update link +### Getting Demo Sources +1. Open your git-compatible console or terminal application. +1. Change directory (using the `cd` command) to the folder that you wish to put the demo sources into. **Note:** *Take note of which directory you are in, it will be used again later* +1. Clone the chosen demo repository. Since the demo repository uses submodules, you should specify the --recursive flag when cloning: + + `git clone --recursive https://github.com/Digilent/` +1. *Only if* the chosen demo repository uses multiple branches to contain multiple demos - which is described in the repository's README - then use the steps below to get the correct sources for that branch. + 1. Change the working directory to the folder the repo was cloned into: + + `cd ` + 1. If you don't know if your chosen demo repository contains multiple demo branches, or if you don't know the name of the demo branch you want to check out, the following command can be used to list all available branches: + + `git branch -a` + 1. Check out the branch for the demo you wish to access: + + `git checkout ` + 1. When checking out a branch, make sure to run the following commands. This will make sure that the correct versions are used for any sources that are included in the demo as submodules. + + `git submodule init` + + `git submodule update` +### Initializing and Building the Vivado Project +1. Launch the version of Vivado that your chosen demo targets. +1. Once Vivado is open, open the TCL Console at the bottom of the screen. +1. To initialize and open the Vivado project, run the following command in the TCL console, changing `` to match the location of the directory that you noted down in Step 2 of the *Getting Demo Sources* section: + + `set argv ""; source //scripts/digilent_vivado_checkout.tcl` +1. At this point you now have access to the Vivado Project and all of its sources. The project can be viewed, changes can be made, a bitstream can be generated, and hardware handoff file (HDF) can be generated. For Standalone Hardware demos, the Quick Guide ends here. The introduction of the next section will tell you how to determine whether your chosen demo is a Standalone Hardware demo or not. +### Final Notes +At this point, you have access to a working copy of the demo repository. The chosen demo's README or wiki page will contain instructions on how to use this demo once it is programmed onto your board. + +For technical support, please visit the [Digilent Forums](https://forum.digilentinc.com/forum/4-fpga). + +This concludes the *Quick Guide*. The remainder of this document discusses the implementation of the digilent-vivado-scripts repository and how to use the scripts in more technical detail. + +---------------- +## Python Frontend +A front-end script, git_vivado.py, is provided to parse command line arguments and call into Vivado at the command line. This script has three subcommands: "checkout", "checkin", and "release". Each of these subcommands has its own help menu, which explains the arguments that can be passed to the script, as well as show what the default values of each of these arguments will be. All paths passed to the script are assumed to be relative to the current working directory. + +**Note**: *Each script can instead be manually sourced within the TCL console in Vivado. When doing so, take care to properly set the `argv` variable, as described in each scripts' Example Usage subsection* + +-------------- +## Commands / Scripts +### Checkout +#### Description +This subcommand calls into digilent_vivado_checkout.tcl in order to create a Vivado project, in the form of an XPR file, using the sources and scripts contained in the project repository. +#### Optional Arguments +1. `-r `: Path to the repository directory. Default: `/..` +1. `-x `: Path to the project .xpr file the repo is to be checked out into. Default: `/proj/.xpr` +1. `-v `: Vivado version number. Default contained in config.ini. (Python only) + +**Note**: *All paths passed as arguments must either be absolute or relative to the current working directory.* +#### Example Usage +##### Python: +> `python3 git_vivado.py checkout -r D:/Github/Zybo-Z7-10-HDMI` + +##### TCL: +> `set argv "-r D:/Github/Zybo-Z7-10-HDMI"` + +> `source digilent-vivado-checkout.tcl` + +----------- +### Checkin +#### Description +This subcommand calls into digilent_vivado_checkin.tcl in order to collect sources and generate needed scripts from a Vivado project into the repository structure described below. Files required for checkout *that are not already present* in the repository (such as project_info.tcl and gitignores), are automatically created. These files are not overwritten if they already exist. +#### Optional Arguments +1. `-r `: Path to the repository directory. Default: `/..` +1. `-x `: Path to the project .xpr file to be processed for checkin. Default: `/proj/*.xpr` +1. `-v `: Vivado version number. Default contained in config.ini. (Python only) + +**Note**: *All paths passed as arguments must either be absolute or relative to the current working directory.* +#### Example Usage +##### Python: +> `python3 git_vivado.py checkin -r D:/Github/Zybo-Z7-10-HDMI` + +##### TCL: +> `set argv "-r D:/Github/Zybo-Z7-10-HDMI"` + +> `source digilent-vivado-checkin.tcl` + +------------------------------------ +## Other Files and Overall Structure +### Configuration File +The digilent-vivado-scripts repository contains a file named `config.ini`. This file contains several values used by the Python frontend to determine what the default arguments for the different subcommands should be. It has not yet been decided how this file should be managed/version-controlled. See *Known Issues* at the bottom of this document for a little more information. + +### Repository Structure +In order to ensure that any changes to this repository do not break the projects that use them, it is expected that this repository will be used as a submodule of each project repository that is intended to use them. + +* `/scripts`: Submodule containing the scripts described by this document. +* `/hw_handoff`: Used to contain the hardware handoff file. +* `/proj`: Used to contain a checked-out Vivado project, and cached generated sources. +* `/release`: Contains temporary files necessary to generate a release zip archive. +* `/repo`: Contains local IP, IP submodules. +* `/src`: Contains source files for the Vivado Project. + * `/src/bd`: Contains a TCL script used to re-create a block design. + * `/src/constraints`: Contains XDC constraint files. + * `/src/hdl`: Contains Verilog and VHDL source files. + * `/src/ip`: Contains XCI files describing IP to be instantiated in non-IPI projects. + * `/src/others`: Contains all other required sources, such as memory initialization files. +* `/.gitignore`: File describing which sources should be version controlled. Template is generated by the checkin process. +* `/.gitmodules`: File describing submodules of the repository. Automatically maintained by the `git submodule` command. +* `/project_info.tcl`: Script generated by first-time checkin used to save and re-apply project settings like board/part values. This can be modified after initial creation to manually configure settings that are not initially supported. **Note**: *This script should be deleted and recreated when porting a project from one board to another.* +* `/README.md`: Markdown file describing the project and the process needed to use it, from downloading the release archive, to programming the FPGA. + +------------ +## Workflows + +### 1. Cloning a Repo that uses this Submodule +In a console, first change the working directory (`cd`) to the location you wish to place the local version of the repo you will be cloning. + +Clone the repository from github, using the `--recursive` flag, in order to pick up this and any other submodules installed in the repo. + + * `git clone --recursive ` + +**Important:** *Further example commands in this document assume that the working directory of the console you are running them in has been set to the cloned repo directory: `cd `* + +If the repo was cloned non-recursively, the repo's submodules must be initialized from a console: + + * `git submodule init` + +#### Vivado +Once the repo exists locally, the Vivado project can be checked out from source. To do this, use the following command: + + * `python3 ./digilent-vivado-scripts/git_vivado.py checkout` + +Alternatively, the project can be checked out from within Vivado, by calling the following command in the TCL console: + + * `set argv ""; source ./digilent-vivado-scripts/digilent_vivado_checkout.tcl` + +Both of these commands create a Vivado project within the repository's `proj` folder. In the case of the Python command, the project then needs to be opened from within Vivado. + +### 2. Creating a New Project +1. Create a folder on your computer to hold the project repository. Use the naming convention `--` (for example: `Zybo-Z7-20-DMA`). This folder will be referred to as the "local repo" + +2. Create a repository on GitHub for your project with Digilent as the owner. Name it the same as the local repo folder. Do not have Github create a README, gitignore file, or license for you. This repository will be referred to as the "remote repo". + +3. In a command line interface (git bash is recommended) cd into the local repo. Call the following set of commands, in order to initialize the repository, add these scripts to it, and set its remote. + * `git init` + * `git submodule add https://github.com/Digilent/digilent-vivado-scripts` + * `git remote add origin ` + +4. While creating and developing your project using Vivado, there are a few guidelines to follow: + * When creating the project, make sure to place the Vivado project in a folder named `proj` in the local repo. + * When exporting hardware, make sure to export to the folder named `hw_handoff` in the local repo. + * If IPs or interfaces from [vivado-library](https://github.com/Digilent/vivado-library) are required, create a folder called `repo` in the local repo, and add vivado-library as a submodule within that folder. + +5. Call the command below. This command can be called from anywhere in your filesystem, with relative paths changed as required. Missing required folders and files are automatically created, including gitignores. **Note:** *Invoking the script in this way uses all default arguments, which assume that the local repo directory structure is used. See* Creating a Repo from a Local Project, *below, for an alternate method.* + * `python3 ./digilent-vivado-scripts/git_vivado.py checkin` + +6. Create a README for the repo that specifies what the project is supposed to do and how to use a release archive for it. See *Using a Release Archive*, below, and the file `template_README.md` in digilent-vivado-scripts for more information. + +7. Add, commit, and push your changes to the remote repo: + + * `git add .` + * `git commit -m "Initial Commit"` + * `git push origin master` + +8. Create and upload a release ZIP to Github - see *Creating a Release Archive* below. + +---- +### 3. Creating a Repo from a Local Project +If your new project was not created following the directory structure described in *Creating a New Project*, above, this is the workflow to follow. This flow is a little more in depth. It assumes that a project has already been created. + +1. Create a repository on GitHub for your project with Digilent as the owner. Name it the same as the local repo folder. Do not have Github create a README, gitignore file, or license for you. This repository will be referred to as the "remote repo". Clone this repository to your computer - the folder where the repository is placed will be referred to as the "local repo". + * `cd ` + * `git clone --recursive ` + +2. In a command line interface (git bash is recommended) cd into the local repo. Call the following command in order add these scripts to the repository. + * `git submodule add https://github.com/Digilent/digilent-vivado-scripts` + +3. Use the checkin command of git_vivado.py to check the local project into the local repo, adding required folders, required files, and the projects sources: + * `cd digilent-vivado-scripts` + * `python3 git_vivado.py checkin -x ` + * `cd ..` + +4. If any changes need to be made to the project during the checkout process, the project_info.tcl generated by the checkin command should be manually edited. + +5. Create a README for the repo that specifies what the project is supposed to do and how to use a release archive for it. See *Using a Release Archive*, below, and the file `template_README.md` in digilent-vivado-scripts for more information. + +6. Add, commit, and push your changes to the remote repo: + * `git add .` + * `git commit -m "Initial Commit"` + * `git push origin master` + +7. Create and upload a release ZIP to Github - see *Creating a Release Archive* below. + + +---- +### 4. Making Changes to a Project that uses this Submodule +1. Clone the Vivado project to be changed. **Note**: *Pull the repo instead, if you already have a local instance of the project.* + * `git clone --recursive ` + +2. In a command line interface (git bash is recommended for Windows) cd into the local project. + +**NOTE**: Steps 3, 4, and 5 are only required if changes to the Vivado project are required. + +3. Call the command below. This command can be called from anywhere in your filesystem, with the relative path to git_vivado. This will also create a gitignore file for the repository. Default arguments will create the XPR at `/proj/.xpr`. + * `python3 /git_vivado.py checkout` + +4. Open the project in Vivado and make any changes necessary (perhaps upgrading IP or fixing a bug). Build the project. Do NOT export hardware yet. + +5. Call the command below. This command can be called from anywhere in your filesystem, with the relative path to git_vivado changed as required. Default arguments are fine, as they assume the use of the `proj` folder. + * `python3 /git_vivado.py checkin` + +7. Make sure to update the repo's README as required. + +8. Add, commit, and push your changes. + * `git add .` + * `git commit -m "Write an informative message here"` + * `git push origin master` + +9. Export the hardware platform from Vivado into the local repo's `hw_handoff` folder. Commit and push it with the commit message "Export Hardware". + +10. Create and upload a release ZIP to GitHub - see *Creating a Release Archive* below. + +---- +### 5. Creating a Release Archive +1. If a README has not been created for the repo, first create one. + +2. Use Vivado's File > Project > Archive menu option to create a release ZIP file for the project. This will package all sources depended on by the project, including IP and board files into a single ZIP, allowing it to be used on a system that does not have these sources previously installed. + +3. Take the new ZIP archive, and add a minor version number to its name, such that the name follows the pattern: `--.zip` (for example, `Zybo-Z7-20-DMA-2018.2-3.zip`). + +4. Draft a new release on Github and upload the ZIP to it. Give the release a descriptive title including the name of the project and the tool version number it supports. Use the format `v-` (for example, `v2018.2-3`) for the version tag. Add text specifying the name of the ZIP that the user must download to the release's description field. + +5. If the project has a software component, review appropriate documentation to release it as well. + +---- +## Known Issues +* Each developer may need their own version of the configuration file, config.ini, for each project they are working on. The configuration file should be moved to somewhere outside of the repo submodule to accomodate this, in a predictable location on Linux and Windows. The Python script will need to be updated to accomodate this, a location and less generic name will need to be chosen for the configuration file. Additional note, requiring that a single Xilinx install directory containing all versions to be used be included in the path may be a better solution. +* There is some danger that modifications to Digilent's board files may break existing projects, it may be worth considering adding the vivado-boards repository as a submodule to project repositories. diff --git a/hw/digilent-vivado-scripts/config.ini b/hw/digilent-vivado-scripts/config.ini new file mode 100644 index 0000000..9052bbb --- /dev/null +++ b/hw/digilent-vivado-scripts/config.ini @@ -0,0 +1,6 @@ +[Windows] +VivadoInstallPath = C:/Xilinx/Vivado +VivadoVersion = 2020.1 +[Linux] +VivadoInstallPath = /opt/Xilinx/Vivado +VivadoVersion = 2020.1 \ No newline at end of file diff --git a/hw/digilent-vivado-scripts/digilent_vivado_checkin.tcl b/hw/digilent-vivado-scripts/digilent_vivado_checkin.tcl new file mode 100644 index 0000000..e3ea8b9 --- /dev/null +++ b/hw/digilent-vivado-scripts/digilent_vivado_checkin.tcl @@ -0,0 +1,220 @@ +# Note: argument order does not matter when setting argv; all arguments are optional +# Usage (No Defaults): +# set argv "-r -x -v " +# source digilent_vivado_checkin.tcl +# Usage (All Defaults): +# set argv "" +# source digilent_vivado_checkin.tcl +# TODO: add debug flag for argument checking + +set script_dir [file normalize [file dirname [info script]]] + +foreach arg $argv { + puts $arg +} + +# Collect local sources, move them to ../src/ + +# Handle repo_path argument +set idx [lsearch ${argv} "-r"] +if {${idx} != -1} { + set repo_path [glob -nocomplain [file normalize [lindex ${argv} [expr {${idx}+1}]]]] +} else { + # Default + set repo_path [file normalize [file join [file dirname [info script]] ..]] +} + +# Handle xpr_path argument +set idx [lsearch ${argv} "-x"] +if {${idx} != -1} { + set xpr_path [glob -nocomplain [file normalize [lindex ${argv} [expr {${idx}+1}]]]] +} else { + # Default + set xpr_path [glob -nocomplain "${repo_path}/proj/*.xpr"] +} +if {[llength ${xpr_path}] != 1} { + puts "ERROR: XPR not found" +} else { + set xpr_path [lindex ${xpr_path} 0] +} + +# Handle vivado_version argument +set idx [lsearch ${argv} "-v"] +if {${idx} != -1} { + set vivado_version [lindex ${argv}] +} else { + set vivado_version [version -short] +} + +set vivado_version [lindex $argv 2]; # unused + +# Other variables +set force_overwrite_info_script 0; # included for possible argument support in future +set proj_file [file tail $xpr_path] +set proj_dir [file dirname $xpr_path] +set proj_name [file rootname [file tail $proj_file]] + +puts "INFO: Checking project \"$proj_file\" into version control." +set already_opened [get_projects -filter "DIRECTORY==$proj_dir && NAME==$proj_name"] +if {[llength $already_opened] == 0} { + open_project $xpr_path +} else { + current_project [lindex $already_opened 0] +} + + + +set required_dirs [list \ + $repo_path/proj \ + $repo_path/hw_handoff \ + $repo_path/src \ + $repo_path/src/bd \ + $repo_path/src/constraints \ + $repo_path/src/ip \ + $repo_path/src/hdl \ + $repo_path/src/other \ + $repo_path/repo \ + $repo_path/repo/local \ +] +set required_files [list \ + $repo_path/proj/.keep \ + $repo_path/hw_handoff/.keep \ + $repo_path/src/bd/.keep \ + $repo_path/src/constraints/.keep \ + $repo_path/src/ip/.keep \ + $repo_path/src/hdl/.keep \ + $repo_path/src/other/.keep \ + $repo_path/repo/local/.keep \ +] +set files [list] + +# Create any missing required directories and files +foreach d $required_dirs { + if {[file exists $d] == 0} { + file mkdir $d + } +} +foreach f $required_files { + if {[file exists $f] == 0} { + close [open $f "w"] + } +} + +# Save source files, including block design tcl script +# WARNING: This script does not capture any non-xdc files for block-design projects +set bd_files [get_files -of_objects [get_filesets sources_1] -filter "NAME=~*.bd"] +if {[llength $bd_files] > 1} { + puts "ERROR: This script cannot handle projects containing more than one block design!" +} elseif {[llength $bd_files] == 1} { + set bd_file [lindex $bd_files 0] + open_bd_design $bd_file + set bd_name [file tail [file rootname [get_property NAME $bd_file]]] + set script_name "$repo_path/src/bd/${bd_name}.tcl" + puts "INFO: Checking in ${script_name} to version control." + write_bd_tcl -force -make_local $script_name + # TODO: Add support for "Add Module" IPI features (check in hdl files included in sources_1, but not any ip fileset) +} else { + foreach source_file [get_files -of_objects [get_filesets sources_1]] { + set origin [get_property name $source_file] + set skip 0 + if {[file extension $origin] == ".vhd"} { + set subdir hdl + } elseif {[file extension $origin] == ".v"} { + set subdir hdl + } elseif {[file extension $origin] == ".sv"} { + set subdir hdl + } elseif {[file extension $origin] != ".bd" && [file extension $origin] != ".xci"} { + set subdir other + } else { + set skip 1 + } + + foreach ip [get_ips] { + set ip_dir [get_property IP_DIR $ip] + set source_length [string length $source_file] + set dir_length [string length $ip_dir] + if {$source_length >= $dir_length && [string range $source_file 0 $dir_length-1] == $ip_dir} { + set skip 1 + } + } + + if {$skip == 0} { + puts "INFO: Checking in [file tail $origin] to version control." + set target $repo_path/src/$subdir/[file tail $origin] + if {[file exists $target] == 0} { # TODO: this may not be safe; remind users to make sure to delete any unused files from version control + file copy -force $origin $target + } + } + } + foreach ip [get_ips] { + set origin [get_property ip_file $ip] + set ipname [get_property name $ip] + set dir "$repo_path/src/ip/$ipname" + if {[file exists $dir] == 0} { + file mkdir $dir + } + set target $dir/[file tail $origin] + puts "INFO: Checking in [file tail $origin] to version control." + if {[file exists $target] == 0} { + # TODO: this may not be safe; remind users to make sure to delete any unused files from version control + file copy -force $origin $target + } + } + # TODO: foreach file in /src/ip, if it wasn't just checked in, delete it +} +foreach constraint_file [get_files -of_objects [get_filesets constrs_1]] { + set origin [get_property name $constraint_file] + set target $repo_path/src/constraints/[file tail $origin] + puts "INFO: Checking in [file tail $origin] to version control." + if {[file exists $target] == 0} { # TODO: this may not be safe; remind users to make sure to delete any unused files from version control + file copy -force $origin $target + } +} +# TODO: foreach file in /src/constraints, if it wasn't just checked in, delete it + +# Save project-specific settings into project_info.tcl +# TODO: will break if multiple projects are open +# project_info.tcl will only be created if it doesn't exist - if it has been manually deleted by the user, or if this is the first time this repo is checked in +if {[file exists $repo_path/project_info.tcl] == 0 || $force_overwrite_info_script != 0} { + set proj_obj [get_projects [file rootname $proj_file]] + + set board_part [current_board_part -quiet] + set part [get_property part $proj_obj] + set default_lib [get_property default_lib $proj_obj] + set simulator_language [get_property simulator_language $proj_obj] + set target_language [get_property target_language $proj_obj] + + puts "INFO: Checking in project_info.tcl to version control." + + set var_map [list $part \ + $default_lib \ + $simulator_language \ + $target_language \ + ] + + if {$board_part ne ""} { + lappend var_map $board_part + } + + set file_name $repo_path/project_info.tcl + set dfid [open $file_name "w"] + set sfid [open $script_dir/templates/project_info.tcl "r"] + + while { [gets $sfid line] >= 0 } { + puts $dfid [string map $var_map $line] + } + + close $dfid + close $sfid +} + +# if .gitignore does not exist, create it +set master_gitignore [file join $repo_path .gitignore] +if {[file exists $master_gitignore] == 0} { + puts "WARNING: This repository does not contain a master gitignore. creating one now." + set target $master_gitignore + set origin $script_dir/templates/hw.gitignore + file copy -force $origin $target +} + +puts "INFO: Project $proj_file has been checked into version control" \ No newline at end of file diff --git a/hw/digilent-vivado-scripts/digilent_vivado_checkout.tcl b/hw/digilent-vivado-scripts/digilent_vivado_checkout.tcl new file mode 100644 index 0000000..a8c2b36 --- /dev/null +++ b/hw/digilent-vivado-scripts/digilent_vivado_checkout.tcl @@ -0,0 +1,203 @@ +# Note: argument order does not matter when setting argv; all arguments are optional +# Usage (No Defaults): +# set argv "-r -x -v " +# source digilent_vivado_checkout.tcl +# Usage (All Defaults): +# set argv "" +# source digilent_vivado_checkout.tcl +# TODO: add debug flag for argument checking + +# Handle repo_path argument +set idx [lsearch ${argv} "-r"] +if {${idx} != -1} { + set repo_path [glob -nocomplain [file normalize [lindex ${argv} [expr {${idx}+1}]]]] +} else { + # Default + set repo_path [file normalize [file dirname [info script]]/..] +} + +# Handle xpr_path argument +set idx [lsearch ${argv} "-x"] +if {${idx} != -1} { + set xpr_path [file normalize [lindex ${argv} [expr {${idx}+1}]]] +} else { + # Default + set xpr_path [file join ${repo_path} proj [file tail $repo_path]].xpr] +} + + +# Handle vivado_version argument +set idx [lsearch ${argv} "-v"] +if {${idx} != -1} { + set vivado_version [lindex ${argv} [expr {${idx}+1}]] +} else { + # Default + set vivado_version [version -short] +} + +# Other variables +set vivado_year [lindex [split $vivado_version "."] 0] +set proj_name [file rootname [file tail $xpr_path]] + +puts "INFO: Creating new project \"$proj_name\" in [file dirname $xpr_path]" + +# Create project +create_project $proj_name [file dirname $xpr_path] + +source $repo_path/project_info.tcl + +# Capture board information for the project +puts "INFO: Capturing board information from $repo_path/project_info.tcl" +set_project_properties_post_create_project $proj_name +set obj [get_projects $proj_name] +set part_name [get_property "part" $obj] + +# Uncomment the following 3 lines to greatly increase build speed while working with IP cores (and/or block diagrams) +puts "INFO: Configuring project IP handling properties" +set_property "corecontainer.enable" "0" $obj +set_property "ip_cache_permissions" "read write" $obj +set_property "ip_output_repo" "[file normalize "$repo_path/proj/cache"]" $obj + +# Create 'sources_1' fileset (if not found) +if {[string equal [get_filesets -quiet sources_1] ""]} { + puts "INFO: Creating sources_1 fileset" + create_fileset -srcset sources_1 +} + +# Create 'constrs_1' fileset (if not found) +if {[string equal [get_filesets -quiet constrs_1] ""]} { + puts "INFO: Creating constrs_1 fileset" + create_fileset -constrset constrs_1 +} + +# Capture project-specific IP settings +puts "INFO: capturing IP-related settings from $repo_path/project_info.tcl" +set_project_properties_pre_add_repo $proj_name + +# Set IP repository paths +puts "INFO: Setting IP repository paths" +set obj [get_filesets sources_1] +set_property "ip_repo_paths" "[file normalize $repo_path/repo]" $obj + +# Refresh IP Repositories +puts "INFO: Refreshing IP repositories" +update_ip_catalog -rebuild + +# Add hardware description language sources +puts "INFO: Adding HDL sources" +add_files -quiet -norecurse $repo_path/src/hdl + +# Add IPs +# TODO: handle IP core-container files +puts "INFO: Adding XCI IP sources" +add_files -quiet [glob -nocomplain $repo_path/src/ip/*/*.xci] + +# Add constraints +puts "INFO: Adding constraints" +add_files -quiet -norecurse -fileset constrs_1 $repo_path/src/constraints + +# Recreate block design +# TODO: handle multiple block designs +set ipi_tcl_files [glob -nocomplain "$repo_path/src/bd/*.tcl"] +set ipi_bd_files [glob -nocomplain "$repo_path/src/bd/*/*.bd"] +if {[llength $ipi_tcl_files] > 1} { + # TODO: quit and log the error + puts "ERROR: This script cannot handle projects containing more than one block design! More than one tcl script foudn in src/bd" +} elseif {[llength $ipi_tcl_files] == 1} { + # Use TCL script to rebuild block design + puts "INFO: Rebuilding block design from script" + # Create local source directory for bd + if {[file exist "[file rootname $xpr_path].srcs"] == 0} { + file mkdir "[file rootname $xpr_path].srcs" + } + if {[file exist "[file rootname $xpr_path].srcs/sources_1"] == 0} { + file mkdir "[file rootname $xpr_path].srcs/sources_1" + } + if {[file exist "[file rootname $xpr_path].srcs/sources_1/bd"] == 0} { + file mkdir "[file rootname $xpr_path].srcs/sources_1/bd" + } + # Force Non-Remote BD Flow + set origin_dir [pwd] + cd "[file rootname $xpr_path].srcs/sources_1" + set run_remote_bd_flow 0 + source [lindex $ipi_tcl_files 0] + cd $origin_dir +} elseif {[llength $ipi_bd_files] > 1} { + # TODO: quit and log the error + puts "ERROR: This script cannot handle projects containing more than one block design! More than one bd file foudn in src/bd" +} elseif {[llength $ipi_bd_files] == 1} { + # Add block design from .bd file and sources + puts "INFO: Rebuilding block design from BD fileset" + add_files -norecurse -quiet -fileset sources_1 [glob -nocomplain $repo_path/src/bd/*/*.bd] + open_bd_design [glob -nocomplain $repo_path/src/bd/*/*.bd] + set design_name [get_bd_designs] + set file "$repo_path/src/bd/$design_name/$design_name.bd" + set file [file normalize $file] + set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] + if { ![get_property "is_locked" $file_obj] } { + set_property "synth_checkpoint_mode" "Hierarchical" $file_obj + } +} + +# Make sure IPs are upgraded to the most recent version +foreach ip [get_ips -filter "IS_LOCKED==1"] { + upgrade_ip -vlnv [get_property UPGRADE_VERSIONS $ip] $ip + export_ip_user_files -of_objects $ip -no_script -sync -force -quiet +} + +# Generate the wrapper for the root design +catch { + # catch block prevents projects without a block design from erroring at this step + set bd_name [get_bd_designs -of_objects [get_bd_cells /]] + set bd_file [get_files $bd_name.bd] + set wrapper_file [make_wrapper -files $bd_file -top -force] + import_files -quiet -force -norecurse $wrapper_file + + set obj [get_filesets sources_1] + set_property "top" "${bd_name}_wrapper" $obj +} + +# Create 'synth_1' run (if not found) +if {[string equal [get_runs -quiet synth_1] ""]} { + puts "INFO: Creating synth_1 run" + create_run -name synth_1 -part $part_name -flow {Vivado Synthesis $vivado_year} -strategy "Vivado Synthesis Defaults" -constrset constrs_1 +} else { + set_property strategy "Vivado Synthesis Defaults" [get_runs synth_1] + set_property flow "Vivado Synthesis $vivado_year" [get_runs synth_1] +} +puts "INFO: Configuring synth_1 run" +set obj [get_runs synth_1] +set_property "part" $part_name $obj +set_property "steps.synth_design.args.flatten_hierarchy" "none" $obj +set_property "steps.synth_design.args.directive" "RuntimeOptimized" $obj +set_property "steps.synth_design.args.fsm_extraction" "off" $obj + +# Set the current synth run +puts "INFO: Setting current synthesis run" +current_run -synthesis [get_runs synth_1] + +# Create 'impl_1' run (if not found) +if {[string equal [get_runs -quiet impl_1] ""]} { + puts "INFO: Creating impl_1 run" + create_run -name impl_1 -part $part_name -flow {Vivado Implementation $vivado_year} -strategy "Vivado Implementation Defaults" -constrset constrs_1 -parent_run synth_1 +} else { + set_property strategy "Vivado Implementation Defaults" [get_runs impl_1] + set_property flow "Vivado Implementation $vivado_year" [get_runs impl_1] +} +puts "INFO: Configuring impl_1 run" +set obj [get_runs impl_1] +set_property "part" $part_name $obj +set_property "steps.opt_design.args.directive" "RuntimeOptimized" $obj +set_property "steps.place_design.args.directive" "RuntimeOptimized" $obj +set_property "steps.route_design.args.directive" "RuntimeOptimized" $obj + +# Set the current impl run +puts "INFO: Setting current implementation run" +current_run -implementation [get_runs impl_1] + +# Capture project-specific IP settings +puts "INFO: capturing run settings from $repo_path/project_info.tcl" +set_project_properties_post_create_runs $proj_name + +puts "INFO: Project created: [file tail $proj_name]" +puts "INFO: Exiting Vivado" \ No newline at end of file diff --git a/hw/digilent-vivado-scripts/git_vivado.py b/hw/digilent-vivado-scripts/git_vivado.py new file mode 100644 index 0000000..522acd0 --- /dev/null +++ b/hw/digilent-vivado-scripts/git_vivado.py @@ -0,0 +1,207 @@ +# PYTHON 3.X.X REQUIRED!!! + +import os +import sys +import configparser +import argparse +import platform + +def accept_warning(s): + c = '' + d = {'Y': True, 'y': True, 'N': False, 'n': False} + while c not in d: + c = input('Warning: %s Y/N? ' % s) + return d[c] + +def do_checkin(args): + DEBUG_NO_VIVADO = args['DEBUG_NO_VIVADO'] + DEBUG_VIVADO_TCL_TRACE = args['DEBUG_VIVADO_TCL_TRACE'] + + vivado_cmd = args['vivado_cmd'].replace('\\', '/') + script_path = os.path.join(args['script_dir'], 'digilent_vivado_checkin.tcl').replace('\\', '/') + xpr_path = args['xpr_path'].replace('\\', '/') + repo_path = args['repo_path'].replace('\\', '/') + version = args['version'].replace('\\', '/') + + if not args['force'] and not accept_warning('Files and directories contained in %s may be overwritten. Do you wish to continue?' % repo_path): + sys.exit() + + print('Checking in project %s to repo %s' % (os.path.basename(xpr_path), os.path.basename(repo_path))) + + if DEBUG_NO_VIVADO: + print ('vivado_cmd: %s' % vivado_cmd) + print ('script_path: %s' % script_path) + print ('xpr_path: %s' % xpr_path) + print ('repo_path: %s' % repo_path) + print ('version: %s' % version) + else: + notrace = '' if DEBUG_VIVADO_TCL_TRACE else ' -notrace' + os.system("%s -mode batch -source %s%s -tclargs -x %s -r %s -v %s" % (vivado_cmd, script_path, notrace, xpr_path, repo_path, version)) + +def do_checkout(args): + DEBUG_NO_VIVADO = args['DEBUG_NO_VIVADO'] + DEBUG_VIVADO_TCL_TRACE = args['DEBUG_VIVADO_TCL_TRACE'] + + vivado_cmd = args['vivado_cmd'].replace('\\', '/') + script_path = os.path.join(args['script_dir'], 'digilent_vivado_checkout.tcl').replace('\\', '/') + xpr_path = args['xpr_path'].replace('\\', '/') + repo_path = args['repo_path'].replace('\\', '/') + version = args['version'].replace('\\', '/') + + + if not args['force'] and not accept_warning('Files and directories contained in %s may be overwritten. Do you wish to continue?' % os.path.dirname(xpr_path)): + sys.exit() + + print('Checking out project %s from repo %s' % (os.path.basename(xpr_path), os.path.basename(repo_path))) + notrace = '' if DEBUG_VIVADO_TCL_TRACE else ' -notrace' + cmd = "%s -mode batch -source %s%s -tclargs -x %s -r %s -v %s" % ( + vivado_cmd, + script_path, + notrace, + # arguments + xpr_path, + repo_path, + version + ) + if DEBUG_NO_VIVADO: + print ('vivado_cmd: %s' % vivado_cmd) + print ('script_path: %s' % script_path) + print ('xpr_path: %s' % xpr_path) + print ('repo_path: %s' % repo_path) + print ('version: %s' % version) + print(cmd) + else: + os.system(cmd) + +if __name__ == "__main__": + # Parse CONFIG.INI + script_dir = os.path.dirname(os.path.abspath(sys.argv[0])) + project_name = os.path.basename(os.path.abspath(os.path.join(script_dir, '..'))) + config = configparser.ConfigParser() + config.read(os.path.join(script_dir, "config.ini")) + operating_system = platform.system() + config_settings = config[operating_system] + + # Default arguments assume that this script is contained in a submodule within the target repository + default_repo_path = os.path.abspath(os.path.join(script_dir, '..')) + default_xpr_path = os.path.abspath(os.path.join(script_dir, '..', 'proj', '%s.xpr' % project_name)) + default_version = config_settings['VivadoVersion'] + + # Parse SYS.ARGV + parser = argparse.ArgumentParser(description='Handles vivado project git repo operations') + parser.add_argument( + '-f', + dest='force', + default=False, + action='store_true', + help='Force overwrite of existing files and folders' + ) + subparsers = parser.add_subparsers(help='sub-command help') + + # Checkin Arguments + parser_checkin = subparsers.add_parser( + 'checkin', + help='Checks in XPR to REPO', + formatter_class=argparse.RawTextHelpFormatter + ) + parser_checkin.set_defaults(func=do_checkin) + # Optional Args + parser_checkin.add_argument( + '-r', + dest='repo_path', + type=str, + default=default_repo_path, + help='Path to target repository from\nDefault = %s' % (default_repo_path) + ) + parser_checkin.add_argument( + '-x', + dest='xpr_path', + type=str, + default=default_xpr_path, + help='Path to XPR file\nDefault = %s' % (default_xpr_path) + ) + parser_checkin.add_argument( + '-v', + dest='version', + type=str, + default=default_version, + help='Vivado version number 20##.#\nDefault = %s' % (default_version) + ) + + # Checkout Arguments + parser_checkout = subparsers.add_parser( + 'checkout', + help='Checks out XPR from REPO', + formatter_class=argparse.RawTextHelpFormatter + ) + parser_checkout.set_defaults(func=do_checkout) + # Optional Args + parser_checkout.add_argument( + '-r', + dest='repo_path', + type=str, + default=default_repo_path, + help='Path to target repository from\nDefault = %s' % (default_repo_path) + ) + parser_checkout.add_argument( + '-x', + dest='xpr_path', + type=str, + default=default_xpr_path, + help='Path to XPR file\nDefault = %s' % (default_xpr_path) + ) + parser_checkout.add_argument( + '-v', + dest='version', + type=str, + default=default_version, + help='Vivado version number 20##.#\nDefault = %s' % (default_version) + ) + + # Parse Arguments + args = parser.parse_args() + + funcargs = {'script_dir': script_dir} + + if not hasattr(args, 'func'): + print("Please select a subcommand to execute. See this command's help page") + sys.exit() + + if hasattr(args, 'force'): + funcargs['force'] = args.force + + if hasattr(args, 'repo_path'): + funcargs['repo_path'] = os.path.abspath(os.path.join(os.getcwd(), args.repo_path)) + + if hasattr(args, 'xpr_path'): + if args.xpr_path[-4:] != '.xpr': + print('Error: xpr_path argument must end in .xpr') + sys.exit() + funcargs['xpr_path'] = os.path.abspath(os.path.join(os.getcwd(), args.xpr_path)) + if args.func == do_checkout and os.path.isfile(funcargs['xpr_path']) or os.path.isdir(funcargs['xpr_path']): + # TODO: add warning about overwriting existing project + # TODO: add clean and overwrite process + # TODO: move project_info.tcl to repo root + print('Error: cannot check out repo when project exists; Please clean out the %s/proj directory' % (funcargs['repo_path'])) + sys.exit() + + if hasattr(args, 'version'): + funcargs['vivado_cmd'] = os.path.join(os.path.abspath(config_settings['VivadoInstallPath']), args.version, 'bin', 'vivado') + funcargs['version'] = args.version + if not os.path.isfile(funcargs['vivado_cmd']): + print('Error: Vivado not installed at %s' % funcargs['vivado_cmd']) + sys.exit() + funcargs['xsct_cmd'] = os.path.join(os.path.abspath(config_settings['SdkInstallPath']), args.version, 'bin', config_settings['XsctFile']) + if not os.path.isfile(funcargs['xsct_cmd']): + print('Error: XSCT not installed at %s' % funcargs['xsct_cmd']) + sys.exit() + + if hasattr(args, 'temp_directory'): + funcargs['temp_directory'] = args.temp_directory + + DEBUG_NO_VIVADO = False + DEBUG_VIVADO_TCL_TRACE = False + funcargs['DEBUG_NO_VIVADO'] = DEBUG_NO_VIVADO + funcargs['DEBUG_VIVADO_TCL_TRACE'] = DEBUG_VIVADO_TCL_TRACE + + args.func(funcargs) diff --git a/hw/digilent-vivado-scripts/templates/README.md b/hw/digilent-vivado-scripts/templates/README.md new file mode 100644 index 0000000..7aa079e --- /dev/null +++ b/hw/digilent-vivado-scripts/templates/README.md @@ -0,0 +1,81 @@ +\ Demo +==================== + +Description +----------- + +The first paragraph of this section describes what peripherals of the board are used, and what the demo does, at a high level. + +Later paragraphs of this section can go into more detail, describing specific features of the demo, such as what messages can be printed by the demo, what options the user can configure, and important additional requirements. + +Requirements +------------ +* This section contains a bulleted list of hardware and software requirements. +* Typically, this includes the board, with a link to the store page. +* Development environments and other required software, with links to installation guides. +* And any other cables and hardware (HDMI cables and monitors for example) that are required. + +Demo Setup +---------- + +*This section is a step by step guide from downloading the release to programming the board and running the demo. All caps text in "< >" brackets is intended to be replaced in the final README.* + +1. Download the most recent release ZIP archive ("\-\-*.zip") from the repo's [releases page](https://github.com/Digilent/\/releases). + +2. Extract the downloaded ZIP. + +3. Open the XPR project file, found at \/vivado_proj/\.xpr, included in the extracted release archive in Vivado \. + +*Some demos only use Vivado, and not Xilinx SDK. In this case, use the following version of steps 4 to end:* + +4. In the Flow Navigator panel on the left side of the Vivado window, click **Open Hardware Manager**. + +5. Plug the \ into the computer using a MicroUSB cable via it's \ programming port. + +*Do not include step 6 if the demo doesn't use UART.* + +6. Open a serial terminal emulator (such as TeraTerm) and connect it to the \'s serial port, using a baud rate of \. + +7. In the green bar at the top of the Vivado window, click **Open target**. Select **Auto connect** from the drop down menu. + +8. In the green bar at the top of the Vivado window, click **Program device**. + +9. In the Program Device Wizard, enter "\/vivado_proj/\.runs/impl_1/\.bit" into the "Bitstream file" field. Then click **Program**. + +10. The demo will now be programmed onto the \. See the *Description* section of this README to learn how to interact with this demo. + +*For demos that use SDK, use the following version of steps 4 to end:* + +4. Launch Xilinx SDK directly (not through the Vivado file menu). When prompted for a workspace, select "\/sdk_workspace". +5. Once the workspace opens, click the **Import** button. In the resulting dialog, first select *Existing Projects into Workspace*, then click **Next**. Navigate to and select the same sdk_workspace folder. +6. Build the project. **Note**: *Errors are sometimes seen at this step. These are typically resolved by right-clicking on the BSP project and selecting Regenerate BSP Sources.* + +*Here is where hardware setup should be described, for example:* + +7. Plug in the HDMI IN/OUT cables as well as the HDMI capable Monitor/TV. + +8. Open a serial terminal application (such as [TeraTerm](https://ttssh2.osdn.jp/index.html.en) and connect it to the \'s serial port, using a baud rate of \. + +9. In the toolbar at the top of the SDK window, select *Xilinx -> Program FPGA*. Leave all fields as their defaults and click "Program". + +10. In the Project Explorer pane, right click on the "\" application project and select "Run As -> Launch on Hardware (System Debugger)". + +11. The application will now be running on the \. It can be interacted with as described in the first section of this README. + +12. Lastly, the hardware platform must be linked to a hardware handoff, so that changes to the Vivado design can be brought into the SDK workspace. In Vivado, in the toolbar at the top of the window, select *File -> Export -> Export Hardware*. Any Exported Location will do, but make sure to remember the selection, and make sure that the **Include bitstream** box is checked. Click **OK**. + +13. In SDK, right click on the \*_hw_platform_\* project, and select *Change Hardware Platform Specification*. Click **Yes** in response to the warning. In the resulting dialog, navigate to and select the .hdf hardware handoff file exported in the previous step, then click **OK**. Now, whenever a modified design is exported from Vivado, on top of the .hdf file, it can be applied to the hardware platform. + +Next Steps +---------- +*This section is primarily used to link to useful resources* + +This demo can be used as a basis for other projects by modifying the hardware platform in the Vivado project's block design or by modifying the SDK application project. + +Check out the \'s [Resource Center](https://reference.digilentinc.com/reference/programmable-logic/\/start) to find more documentation, demos, and tutorials. + +For technical support or questions, please post on the [Digilent Forum](forum.digilentinc.com). + +Additional Notes +---------------- +For more information on how this project is version controlled, refer to the [digilent-vivado-scripts repo](https://github.com/digilent/digilent-vivado-scripts). \ No newline at end of file diff --git a/hw/digilent-vivado-scripts/templates/hw.gitignore b/hw/digilent-vivado-scripts/templates/hw.gitignore new file mode 100644 index 0000000..f811c2b --- /dev/null +++ b/hw/digilent-vivado-scripts/templates/hw.gitignore @@ -0,0 +1,53 @@ +# This is a gitignore file automatically generated by digilent_vivado_checkin.tcl +# The file will not be overwritten unless deleted + +# root +/* +!.gitignore +!README.md +!LICENSE +!project_info.tcl +!proj/ +!repo/ +!src/ +!scripts/ +!hw_handoff/ + +# vivado workspace +proj/* + +# ip repository +repo/** +!repo/vivado-library +repo/vivado-library/** +!repo/local +!repo/local/** +!repo/cache +repo/cache/** + +# version controlled sources +src/** +!src/bd +src/bd/** +!src/bd/*.tcl +!src/constraints +src/constraints/** +!src/constraints/*.xdc +!src/hdl +src/hdl/** +!src/hdl/*.v +!src/hdl/*.sv +!src/hdl/*.vhd +!src/ip +!src/ip/* +src/ip/*/** +!src/ip/**/*.xci +!src/other +!src/other/** + +# hardware handoff +hw_handoff/* +!hw_handoff/*.xsa + +# maintain required directories +!**/.keep \ No newline at end of file diff --git a/hw/digilent-vivado-scripts/templates/project_info.tcl b/hw/digilent-vivado-scripts/templates/project_info.tcl new file mode 100644 index 0000000..a0f2c2c --- /dev/null +++ b/hw/digilent-vivado-scripts/templates/project_info.tcl @@ -0,0 +1,19 @@ +# This is an automatically generated file used by digilent_vivado_checkout.tcl to set project options +proc set_project_properties_post_create_project {proj_name} { + set project_obj [get_projects $proj_name] + set_property "part" "" $project_obj + set_property "board_part" "" $project_obj + set_property "default_lib" "" $project_obj + set_property "simulator_language" "" $project_obj + set_property "target_language" "" $project_obj +} + +proc set_project_properties_pre_add_repo {proj_name} { + set project_obj [get_projects $proj_name] + # default nothing +} + +proc set_project_properties_post_create_runs {proj_name} { + set project_obj [get_projects $proj_name] + # default nothing +} \ No newline at end of file diff --git a/hw/hw_handoff/.keep b/hw/hw_handoff/.keep new file mode 100644 index 0000000..e69de29 diff --git a/hw/proj/.keep b/hw/proj/.keep new file mode 100644 index 0000000..e69de29 diff --git a/hw/repo/cache/.keep b/hw/repo/cache/.keep new file mode 100644 index 0000000..e69de29 diff --git a/hw/repo/local/.keep b/hw/repo/local/.keep new file mode 100644 index 0000000..e69de29 diff --git a/hw/src/bd/.keep b/hw/src/bd/.keep new file mode 100644 index 0000000..e69de29 diff --git a/hw/src/bd/user_35t.tcl b/hw/src/bd/user_35t.tcl new file mode 100644 index 0000000..0b34b8f --- /dev/null +++ b/hw/src/bd/user_35t.tcl @@ -0,0 +1,508 @@ + +################################################################ +# This is a generated script based on design: user_35t +# +# Though there are limitations about the generated script, +# the main purpose of this utility is to make learning +# IP Integrator Tcl commands easier. +################################################################ + +namespace eval _tcl { +proc get_script_folder {} { + set script_path [file normalize [info script]] + set script_folder [file dirname $script_path] + return $script_folder +} +} +variable script_folder +set script_folder [_tcl::get_script_folder] + +################################################################ +# Check if script is running in correct Vivado version. +################################################################ +set scripts_vivado_version 2020.1 +set current_vivado_version [version -short] + +if { [string first $scripts_vivado_version $current_vivado_version] == -1 } { + puts "" + catch {common::send_gid_msg -ssname BD::TCL -id 2041 -severity "ERROR" "This script was generated using Vivado <$scripts_vivado_version> and is being run in <$current_vivado_version> of Vivado. Please run the script in Vivado <$scripts_vivado_version> then open the design in Vivado <$current_vivado_version>. Upgrade the design by running \"Tools => Report => Report IP Status...\", then run write_bd_tcl to create an updated script."} + + return 1 +} + +################################################################ +# START +################################################################ + +# To test this script, run the following commands from Vivado Tcl console: +# source user_35t_script.tcl + +# If there is no project opened, this script will create a +# project, but make sure you do not have an existing project +# <./myproj/project_1.xpr> in the current working folder. + +set list_projs [get_projects -quiet] +if { $list_projs eq "" } { + create_project project_1 myproj -part xc7a35tcpg236-1 + set_property BOARD_PART digilentinc.com:cmod_a7-35t:part0:1.1 [current_project] +} + + +# CHANGE DESIGN NAME HERE +variable design_name +set design_name user_35t + +# If you do not already have an existing IP Integrator design open, +# you can create a design using the following command: +# create_bd_design $design_name + +# Creating design if needed +set errMsg "" +set nRet 0 + +set cur_design [current_bd_design -quiet] +set list_cells [get_bd_cells -quiet] + +if { ${design_name} eq "" } { + # USE CASES: + # 1) Design_name not set + + set errMsg "Please set the variable to a non-empty value." + set nRet 1 + +} elseif { ${cur_design} ne "" && ${list_cells} eq "" } { + # USE CASES: + # 2): Current design opened AND is empty AND names same. + # 3): Current design opened AND is empty AND names diff; design_name NOT in project. + # 4): Current design opened AND is empty AND names diff; design_name exists in project. + + if { $cur_design ne $design_name } { + common::send_gid_msg -ssname BD::TCL -id 2001 -severity "INFO" "Changing value of from <$design_name> to <$cur_design> since current design is empty." + set design_name [get_property NAME $cur_design] + } + common::send_gid_msg -ssname BD::TCL -id 2002 -severity "INFO" "Constructing design in IPI design <$cur_design>..." + +} elseif { ${cur_design} ne "" && $list_cells ne "" && $cur_design eq $design_name } { + # USE CASES: + # 5) Current design opened AND has components AND same names. + + set errMsg "Design <$design_name> already exists in your project, please set the variable to another value." + set nRet 1 +} elseif { [get_files -quiet ${design_name}.bd] ne "" } { + # USE CASES: + # 6) Current opened design, has components, but diff names, design_name exists in project. + # 7) No opened design, design_name exists in project. + + set errMsg "Design <$design_name> already exists in your project, please set the variable to another value." + set nRet 2 + +} else { + # USE CASES: + # 8) No opened design, design_name not in project. + # 9) Current opened design, has components, but diff names, design_name not in project. + + common::send_gid_msg -ssname BD::TCL -id 2003 -severity "INFO" "Currently there is no design <$design_name> in project, so creating one..." + + create_bd_design $design_name + + common::send_gid_msg -ssname BD::TCL -id 2004 -severity "INFO" "Making design <$design_name> as current_bd_design." + current_bd_design $design_name + +} + +common::send_gid_msg -ssname BD::TCL -id 2005 -severity "INFO" "Currently the variable is equal to \"$design_name\"." + +if { $nRet != 0 } { + catch {common::send_gid_msg -ssname BD::TCL -id 2006 -severity "ERROR" $errMsg} + return $nRet +} + +set bCheckIPsPassed 1 +################################################################## +# CHECK IPs +################################################################## +set bCheckIPs 1 +if { $bCheckIPs == 1 } { + set list_check_ips "\ +xilinx.com:ip:axi_emc:3.0\ +xilinx.com:ip:axi_gpio:2.0\ +xilinx.com:ip:axi_intc:4.1\ +xilinx.com:ip:axi_timer:2.0\ +xilinx.com:ip:axi_uartlite:2.0\ +xilinx.com:ip:clk_wiz:6.0\ +xilinx.com:ip:mdm:3.2\ +xilinx.com:ip:microblaze:11.0\ +xilinx.com:ip:proc_sys_reset:5.0\ +xilinx.com:ip:xlconcat:2.1\ +xilinx.com:ip:lmb_bram_if_cntlr:4.0\ +xilinx.com:ip:lmb_v10:3.0\ +xilinx.com:ip:blk_mem_gen:8.4\ +" + + set list_ips_missing "" + common::send_gid_msg -ssname BD::TCL -id 2011 -severity "INFO" "Checking if the following IPs exist in the project's IP catalog: $list_check_ips ." + + foreach ip_vlnv $list_check_ips { + set ip_obj [get_ipdefs -all $ip_vlnv] + if { $ip_obj eq "" } { + lappend list_ips_missing $ip_vlnv + } + } + + if { $list_ips_missing ne "" } { + catch {common::send_gid_msg -ssname BD::TCL -id 2012 -severity "ERROR" "The following IPs are not found in the IP Catalog:\n $list_ips_missing\n\nResolution: Please add the repository containing the IP(s) to the project." } + set bCheckIPsPassed 0 + } + +} + +if { $bCheckIPsPassed != 1 } { + common::send_gid_msg -ssname BD::TCL -id 2023 -severity "WARNING" "Will not continue with creation of design due to the error(s) above." + return 3 +} + +################################################################## +# DESIGN PROCs +################################################################## + + +# Hierarchical cell: microblaze_0_local_memory +proc create_hier_cell_microblaze_0_local_memory { parentCell nameHier } { + + variable script_folder + + if { $parentCell eq "" || $nameHier eq "" } { + catch {common::send_gid_msg -ssname BD::TCL -id 2092 -severity "ERROR" "create_hier_cell_microblaze_0_local_memory() - Empty argument(s)!"} + return + } + + # Get object for parentCell + set parentObj [get_bd_cells $parentCell] + if { $parentObj == "" } { + catch {common::send_gid_msg -ssname BD::TCL -id 2090 -severity "ERROR" "Unable to find parent cell <$parentCell>!"} + return + } + + # Make sure parentObj is hier blk + set parentType [get_property TYPE $parentObj] + if { $parentType ne "hier" } { + catch {common::send_gid_msg -ssname BD::TCL -id 2091 -severity "ERROR" "Parent <$parentObj> has TYPE = <$parentType>. Expected to be ."} + return + } + + # Save current instance; Restore later + set oldCurInst [current_bd_instance .] + + # Set parent object as current + current_bd_instance $parentObj + + # Create cell and set as current instance + set hier_obj [create_bd_cell -type hier $nameHier] + current_bd_instance $hier_obj + + # Create interface pins + create_bd_intf_pin -mode MirroredMaster -vlnv xilinx.com:interface:lmb_rtl:1.0 DLMB + + create_bd_intf_pin -mode MirroredMaster -vlnv xilinx.com:interface:lmb_rtl:1.0 ILMB + + + # Create pins + create_bd_pin -dir I -type clk LMB_Clk + create_bd_pin -dir I -from 0 -to 0 -type rst SYS_Rst + + # Create instance: dlmb_bram_if_cntlr, and set properties + set dlmb_bram_if_cntlr [ create_bd_cell -type ip -vlnv xilinx.com:ip:lmb_bram_if_cntlr:4.0 dlmb_bram_if_cntlr ] + set_property -dict [ list \ + CONFIG.C_ECC {0} \ + ] $dlmb_bram_if_cntlr + + # Create instance: dlmb_v10, and set properties + set dlmb_v10 [ create_bd_cell -type ip -vlnv xilinx.com:ip:lmb_v10:3.0 dlmb_v10 ] + + # Create instance: ilmb_bram_if_cntlr, and set properties + set ilmb_bram_if_cntlr [ create_bd_cell -type ip -vlnv xilinx.com:ip:lmb_bram_if_cntlr:4.0 ilmb_bram_if_cntlr ] + set_property -dict [ list \ + CONFIG.C_ECC {0} \ + ] $ilmb_bram_if_cntlr + + # Create instance: ilmb_v10, and set properties + set ilmb_v10 [ create_bd_cell -type ip -vlnv xilinx.com:ip:lmb_v10:3.0 ilmb_v10 ] + + # Create instance: lmb_bram, and set properties + set lmb_bram [ create_bd_cell -type ip -vlnv xilinx.com:ip:blk_mem_gen:8.4 lmb_bram ] + set_property -dict [ list \ + CONFIG.EN_SAFETY_CKT {false} \ + CONFIG.Enable_B {Use_ENB_Pin} \ + CONFIG.Memory_Type {True_Dual_Port_RAM} \ + CONFIG.Port_B_Clock {100} \ + CONFIG.Port_B_Enable_Rate {100} \ + CONFIG.Port_B_Write_Rate {50} \ + CONFIG.Use_RSTB_Pin {true} \ + CONFIG.use_bram_block {BRAM_Controller} \ + ] $lmb_bram + + # Create interface connections + connect_bd_intf_net -intf_net microblaze_0_dlmb [get_bd_intf_pins DLMB] [get_bd_intf_pins dlmb_v10/LMB_M] + connect_bd_intf_net -intf_net microblaze_0_dlmb_bus [get_bd_intf_pins dlmb_bram_if_cntlr/SLMB] [get_bd_intf_pins dlmb_v10/LMB_Sl_0] + connect_bd_intf_net -intf_net microblaze_0_dlmb_cntlr [get_bd_intf_pins dlmb_bram_if_cntlr/BRAM_PORT] [get_bd_intf_pins lmb_bram/BRAM_PORTA] + connect_bd_intf_net -intf_net microblaze_0_ilmb [get_bd_intf_pins ILMB] [get_bd_intf_pins ilmb_v10/LMB_M] + connect_bd_intf_net -intf_net microblaze_0_ilmb_bus [get_bd_intf_pins ilmb_bram_if_cntlr/SLMB] [get_bd_intf_pins ilmb_v10/LMB_Sl_0] + connect_bd_intf_net -intf_net microblaze_0_ilmb_cntlr [get_bd_intf_pins ilmb_bram_if_cntlr/BRAM_PORT] [get_bd_intf_pins lmb_bram/BRAM_PORTB] + + # Create port connections + connect_bd_net -net SYS_Rst_1 [get_bd_pins SYS_Rst] [get_bd_pins dlmb_bram_if_cntlr/LMB_Rst] [get_bd_pins dlmb_v10/SYS_Rst] [get_bd_pins ilmb_bram_if_cntlr/LMB_Rst] [get_bd_pins ilmb_v10/SYS_Rst] + connect_bd_net -net microblaze_0_Clk [get_bd_pins LMB_Clk] [get_bd_pins dlmb_bram_if_cntlr/LMB_Clk] [get_bd_pins dlmb_v10/LMB_Clk] [get_bd_pins ilmb_bram_if_cntlr/LMB_Clk] [get_bd_pins ilmb_v10/LMB_Clk] + + # Restore current instance + current_bd_instance $oldCurInst +} + + +# Procedure to create entire design; Provide argument to make +# procedure reusable. If parentCell is "", will use root. +proc create_root_design { parentCell } { + + variable script_folder + variable design_name + + if { $parentCell eq "" } { + set parentCell [get_bd_cells /] + } + + # Get object for parentCell + set parentObj [get_bd_cells $parentCell] + if { $parentObj == "" } { + catch {common::send_gid_msg -ssname BD::TCL -id 2090 -severity "ERROR" "Unable to find parent cell <$parentCell>!"} + return + } + + # Make sure parentObj is hier blk + set parentType [get_property TYPE $parentObj] + if { $parentType ne "hier" } { + catch {common::send_gid_msg -ssname BD::TCL -id 2091 -severity "ERROR" "Parent <$parentObj> has TYPE = <$parentType>. Expected to be ."} + return + } + + # Save current instance; Restore later + set oldCurInst [current_bd_instance .] + + # Set parent object as current + current_bd_instance $parentObj + + + # Create interface ports + set cellular_ram [ create_bd_intf_port -mode Master -vlnv xilinx.com:interface:emc_rtl:1.0 cellular_ram ] + + set led_2bits [ create_bd_intf_port -mode Master -vlnv xilinx.com:interface:gpio_rtl:1.0 led_2bits ] + + set push_buttons_1bit [ create_bd_intf_port -mode Master -vlnv xilinx.com:interface:gpio_rtl:1.0 push_buttons_1bit ] + + set rgb_led [ create_bd_intf_port -mode Master -vlnv xilinx.com:interface:gpio_rtl:1.0 rgb_led ] + + set usb_uart [ create_bd_intf_port -mode Master -vlnv xilinx.com:interface:uart_rtl:1.0 usb_uart ] + + + # Create ports + set reset [ create_bd_port -dir I -type rst reset ] + set_property -dict [ list \ + CONFIG.POLARITY {ACTIVE_HIGH} \ + ] $reset + set sys_clock [ create_bd_port -dir I -type clk -freq_hz 12000000 sys_clock ] + set_property -dict [ list \ + CONFIG.PHASE {0.000} \ + ] $sys_clock + + # Create instance: axi_emc_0, and set properties + set axi_emc_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_emc:3.0 axi_emc_0 ] + set_property -dict [ list \ + CONFIG.C_MAX_MEM_WIDTH {8} \ + CONFIG.C_MEM0_TYPE {1} \ + CONFIG.C_MEM0_WIDTH {8} \ + CONFIG.C_TAVDV_PS_MEM_0 {8000} \ + CONFIG.C_TCEDV_PS_MEM_0 {8000} \ + CONFIG.C_THZCE_PS_MEM_0 {8000} \ + CONFIG.C_THZOE_PS_MEM_0 {8000} \ + CONFIG.C_TLZWE_PS_MEM_0 {3000} \ + CONFIG.C_TWC_PS_MEM_0 {8000} \ + CONFIG.C_TWP_PS_MEM_0 {8000} \ + CONFIG.EMC_BOARD_INTERFACE {cellular_ram} \ + CONFIG.USE_BOARD_FLOW {true} \ + ] $axi_emc_0 + + # Create instance: axi_gpio_0, and set properties + set axi_gpio_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_gpio:2.0 axi_gpio_0 ] + set_property -dict [ list \ + CONFIG.C_ALL_INPUTS_2 {1} \ + CONFIG.C_GPIO2_WIDTH {1} \ + CONFIG.C_GPIO_WIDTH {2} \ + CONFIG.C_INTERRUPT_PRESENT {1} \ + CONFIG.C_IS_DUAL {1} \ + CONFIG.GPIO2_BOARD_INTERFACE {push_buttons_1bit} \ + CONFIG.GPIO_BOARD_INTERFACE {led_2bits} \ + CONFIG.USE_BOARD_FLOW {true} \ + ] $axi_gpio_0 + + # Create instance: axi_gpio_1, and set properties + set axi_gpio_1 [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_gpio:2.0 axi_gpio_1 ] + set_property -dict [ list \ + CONFIG.C_DOUT_DEFAULT {0x00000007} \ + CONFIG.C_GPIO_WIDTH {3} \ + CONFIG.GPIO_BOARD_INTERFACE {rgb_led} \ + CONFIG.USE_BOARD_FLOW {true} \ + ] $axi_gpio_1 + + # Create instance: axi_intc_0, and set properties + set axi_intc_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_intc:4.1 axi_intc_0 ] + + # Create instance: axi_mem_intercon, and set properties + set axi_mem_intercon [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_interconnect:2.1 axi_mem_intercon ] + set_property -dict [ list \ + CONFIG.M00_HAS_DATA_FIFO {2} \ + CONFIG.M00_HAS_REGSLICE {4} \ + CONFIG.NUM_MI {1} \ + CONFIG.NUM_SI {2} \ + CONFIG.S00_HAS_DATA_FIFO {2} \ + CONFIG.S00_HAS_REGSLICE {4} \ + CONFIG.S01_HAS_DATA_FIFO {2} \ + CONFIG.S01_HAS_REGSLICE {4} \ + CONFIG.SYNCHRONIZATION_STAGES {2} \ + ] $axi_mem_intercon + + # Create instance: axi_timer_0, and set properties + set axi_timer_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_timer:2.0 axi_timer_0 ] + + # Create instance: axi_uartlite_0, and set properties + set axi_uartlite_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_uartlite:2.0 axi_uartlite_0 ] + set_property -dict [ list \ + CONFIG.UARTLITE_BOARD_INTERFACE {usb_uart} \ + CONFIG.USE_BOARD_FLOW {true} \ + ] $axi_uartlite_0 + + # Create instance: clk_wiz_0, and set properties + set clk_wiz_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:clk_wiz:6.0 clk_wiz_0 ] + set_property -dict [ list \ + CONFIG.CLKIN1_JITTER_PS {833.33} \ + CONFIG.CLKOUT1_JITTER {479.872} \ + CONFIG.CLKOUT1_PHASE_ERROR {668.310} \ + CONFIG.CLK_IN1_BOARD_INTERFACE {sys_clock} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {62.500} \ + CONFIG.MMCM_CLKIN1_PERIOD {83.333} \ + CONFIG.MMCM_CLKIN2_PERIOD {10.0} \ + CONFIG.MMCM_CLKOUT0_DIVIDE_F {7.500} \ + CONFIG.RESET_BOARD_INTERFACE {reset} \ + CONFIG.USE_BOARD_FLOW {true} \ + ] $clk_wiz_0 + + # Create instance: mdm_1, and set properties + set mdm_1 [ create_bd_cell -type ip -vlnv xilinx.com:ip:mdm:3.2 mdm_1 ] + + # Create instance: microblaze_0, and set properties + set microblaze_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:microblaze:11.0 microblaze_0 ] + set_property -dict [ list \ + CONFIG.C_ADDR_TAG_BITS {6} \ + CONFIG.C_DCACHE_ADDR_TAG {6} \ + CONFIG.C_DEBUG_ENABLED {1} \ + CONFIG.C_D_AXI {1} \ + CONFIG.C_D_LMB {1} \ + CONFIG.C_ICACHE_LINE_LEN {8} \ + CONFIG.C_ILL_OPCODE_EXCEPTION {0} \ + CONFIG.C_I_LMB {1} \ + CONFIG.C_MMU_ZONES {2} \ + CONFIG.C_M_AXI_D_BUS_EXCEPTION {1} \ + CONFIG.C_M_AXI_I_BUS_EXCEPTION {0} \ + CONFIG.C_NUMBER_OF_PC_BRK {2} \ + CONFIG.C_OPCODE_0x0_ILLEGAL {0} \ + CONFIG.C_UNALIGNED_EXCEPTIONS {0} \ + CONFIG.C_USE_BARREL {1} \ + CONFIG.C_USE_DCACHE {1} \ + CONFIG.C_USE_HW_MUL {1} \ + CONFIG.C_USE_ICACHE {1} \ + CONFIG.C_USE_MMU {0} \ + CONFIG.C_USE_MSR_INSTR {1} \ + CONFIG.C_USE_PCMP_INSTR {1} \ + CONFIG.G_TEMPLATE_LIST {6} \ + CONFIG.G_USE_EXCEPTIONS {1} \ + ] $microblaze_0 + + # Create instance: microblaze_0_axi_periph, and set properties + set microblaze_0_axi_periph [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_interconnect:2.1 microblaze_0_axi_periph ] + set_property -dict [ list \ + CONFIG.NUM_MI {5} \ + CONFIG.SYNCHRONIZATION_STAGES {2} \ + ] $microblaze_0_axi_periph + + # Create instance: microblaze_0_local_memory + create_hier_cell_microblaze_0_local_memory [current_bd_instance .] microblaze_0_local_memory + + # Create instance: rst_clk_wiz_0_100M, and set properties + set rst_clk_wiz_0_100M [ create_bd_cell -type ip -vlnv xilinx.com:ip:proc_sys_reset:5.0 rst_clk_wiz_0_100M ] + set_property -dict [ list \ + CONFIG.RESET_BOARD_INTERFACE {reset} \ + CONFIG.USE_BOARD_FLOW {true} \ + ] $rst_clk_wiz_0_100M + + # Create instance: xlconcat_0, and set properties + set xlconcat_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconcat:2.1 xlconcat_0 ] + + # Create interface connections + connect_bd_intf_net -intf_net axi_emc_0_EMC_INTF [get_bd_intf_ports cellular_ram] [get_bd_intf_pins axi_emc_0/EMC_INTF] + connect_bd_intf_net -intf_net axi_gpio_0_GPIO [get_bd_intf_ports led_2bits] [get_bd_intf_pins axi_gpio_0/GPIO] + connect_bd_intf_net -intf_net axi_gpio_0_GPIO2 [get_bd_intf_ports push_buttons_1bit] [get_bd_intf_pins axi_gpio_0/GPIO2] + connect_bd_intf_net -intf_net axi_gpio_1_GPIO [get_bd_intf_ports rgb_led] [get_bd_intf_pins axi_gpio_1/GPIO] + connect_bd_intf_net -intf_net axi_intc_0_interrupt [get_bd_intf_pins axi_intc_0/interrupt] [get_bd_intf_pins microblaze_0/INTERRUPT] + connect_bd_intf_net -intf_net axi_mem_intercon_M00_AXI [get_bd_intf_pins axi_emc_0/S_AXI_MEM] [get_bd_intf_pins axi_mem_intercon/M00_AXI] + connect_bd_intf_net -intf_net axi_uartlite_0_UART [get_bd_intf_ports usb_uart] [get_bd_intf_pins axi_uartlite_0/UART] + connect_bd_intf_net -intf_net microblaze_0_M_AXI_DC [get_bd_intf_pins axi_mem_intercon/S00_AXI] [get_bd_intf_pins microblaze_0/M_AXI_DC] + connect_bd_intf_net -intf_net microblaze_0_M_AXI_DP [get_bd_intf_pins microblaze_0/M_AXI_DP] [get_bd_intf_pins microblaze_0_axi_periph/S00_AXI] + connect_bd_intf_net -intf_net microblaze_0_M_AXI_IC [get_bd_intf_pins axi_mem_intercon/S01_AXI] [get_bd_intf_pins microblaze_0/M_AXI_IC] + connect_bd_intf_net -intf_net microblaze_0_axi_periph_M00_AXI [get_bd_intf_pins axi_gpio_0/S_AXI] [get_bd_intf_pins microblaze_0_axi_periph/M00_AXI] + connect_bd_intf_net -intf_net microblaze_0_axi_periph_M01_AXI [get_bd_intf_pins axi_gpio_1/S_AXI] [get_bd_intf_pins microblaze_0_axi_periph/M01_AXI] + connect_bd_intf_net -intf_net microblaze_0_axi_periph_M02_AXI [get_bd_intf_pins axi_uartlite_0/S_AXI] [get_bd_intf_pins microblaze_0_axi_periph/M02_AXI] + connect_bd_intf_net -intf_net microblaze_0_axi_periph_M03_AXI [get_bd_intf_pins axi_timer_0/S_AXI] [get_bd_intf_pins microblaze_0_axi_periph/M03_AXI] + connect_bd_intf_net -intf_net microblaze_0_axi_periph_M04_AXI [get_bd_intf_pins axi_intc_0/s_axi] [get_bd_intf_pins microblaze_0_axi_periph/M04_AXI] + connect_bd_intf_net -intf_net microblaze_0_debug [get_bd_intf_pins mdm_1/MBDEBUG_0] [get_bd_intf_pins microblaze_0/DEBUG] + connect_bd_intf_net -intf_net microblaze_0_dlmb_1 [get_bd_intf_pins microblaze_0/DLMB] [get_bd_intf_pins microblaze_0_local_memory/DLMB] + connect_bd_intf_net -intf_net microblaze_0_ilmb_1 [get_bd_intf_pins microblaze_0/ILMB] [get_bd_intf_pins microblaze_0_local_memory/ILMB] + + # Create port connections + connect_bd_net -net axi_gpio_0_ip2intc_irpt [get_bd_pins axi_gpio_0/ip2intc_irpt] [get_bd_pins xlconcat_0/In1] + connect_bd_net -net axi_timer_0_interrupt [get_bd_pins axi_timer_0/interrupt] [get_bd_pins xlconcat_0/In0] + connect_bd_net -net clk_wiz_0_locked [get_bd_pins clk_wiz_0/locked] [get_bd_pins rst_clk_wiz_0_100M/dcm_locked] + connect_bd_net -net mdm_1_debug_sys_rst [get_bd_pins mdm_1/Debug_SYS_Rst] [get_bd_pins rst_clk_wiz_0_100M/mb_debug_sys_rst] + connect_bd_net -net microblaze_0_Clk [get_bd_pins axi_emc_0/rdclk] [get_bd_pins axi_emc_0/s_axi_aclk] [get_bd_pins axi_gpio_0/s_axi_aclk] [get_bd_pins axi_gpio_1/s_axi_aclk] [get_bd_pins axi_intc_0/s_axi_aclk] [get_bd_pins axi_mem_intercon/ACLK] [get_bd_pins axi_mem_intercon/M00_ACLK] [get_bd_pins axi_mem_intercon/S00_ACLK] [get_bd_pins axi_mem_intercon/S01_ACLK] [get_bd_pins axi_timer_0/s_axi_aclk] [get_bd_pins axi_uartlite_0/s_axi_aclk] [get_bd_pins clk_wiz_0/clk_out1] [get_bd_pins microblaze_0/Clk] [get_bd_pins microblaze_0_axi_periph/ACLK] [get_bd_pins microblaze_0_axi_periph/M00_ACLK] [get_bd_pins microblaze_0_axi_periph/M01_ACLK] [get_bd_pins microblaze_0_axi_periph/M02_ACLK] [get_bd_pins microblaze_0_axi_periph/M03_ACLK] [get_bd_pins microblaze_0_axi_periph/M04_ACLK] [get_bd_pins microblaze_0_axi_periph/S00_ACLK] [get_bd_pins microblaze_0_local_memory/LMB_Clk] [get_bd_pins rst_clk_wiz_0_100M/slowest_sync_clk] + connect_bd_net -net reset_1 [get_bd_ports reset] [get_bd_pins clk_wiz_0/reset] [get_bd_pins rst_clk_wiz_0_100M/ext_reset_in] + connect_bd_net -net rst_clk_wiz_0_100M_bus_struct_reset [get_bd_pins microblaze_0_local_memory/SYS_Rst] [get_bd_pins rst_clk_wiz_0_100M/bus_struct_reset] + connect_bd_net -net rst_clk_wiz_0_100M_interconnect_aresetn [get_bd_pins axi_mem_intercon/ARESETN] [get_bd_pins microblaze_0_axi_periph/ARESETN] [get_bd_pins rst_clk_wiz_0_100M/interconnect_aresetn] + connect_bd_net -net rst_clk_wiz_0_100M_mb_reset [get_bd_pins microblaze_0/Reset] [get_bd_pins rst_clk_wiz_0_100M/mb_reset] + connect_bd_net -net rst_clk_wiz_0_100M_peripheral_aresetn [get_bd_pins axi_emc_0/s_axi_aresetn] [get_bd_pins axi_gpio_0/s_axi_aresetn] [get_bd_pins axi_gpio_1/s_axi_aresetn] [get_bd_pins axi_intc_0/s_axi_aresetn] [get_bd_pins axi_mem_intercon/M00_ARESETN] [get_bd_pins axi_mem_intercon/S00_ARESETN] [get_bd_pins axi_mem_intercon/S01_ARESETN] [get_bd_pins axi_timer_0/s_axi_aresetn] [get_bd_pins axi_uartlite_0/s_axi_aresetn] [get_bd_pins microblaze_0_axi_periph/M00_ARESETN] [get_bd_pins microblaze_0_axi_periph/M01_ARESETN] [get_bd_pins microblaze_0_axi_periph/M02_ARESETN] [get_bd_pins microblaze_0_axi_periph/M03_ARESETN] [get_bd_pins microblaze_0_axi_periph/M04_ARESETN] [get_bd_pins microblaze_0_axi_periph/S00_ARESETN] [get_bd_pins rst_clk_wiz_0_100M/peripheral_aresetn] + connect_bd_net -net sys_clock_1 [get_bd_ports sys_clock] [get_bd_pins clk_wiz_0/clk_in1] + connect_bd_net -net xlconcat_0_dout [get_bd_pins axi_intc_0/intr] [get_bd_pins xlconcat_0/dout] + + # Create address segments + assign_bd_address -offset 0x60000000 -range 0x00080000 -target_address_space [get_bd_addr_spaces microblaze_0/Data] [get_bd_addr_segs axi_emc_0/S_AXI_MEM/Mem0] -force + assign_bd_address -offset 0x60000000 -range 0x00080000 -target_address_space [get_bd_addr_spaces microblaze_0/Instruction] [get_bd_addr_segs axi_emc_0/S_AXI_MEM/Mem0] -force + assign_bd_address -offset 0x40000000 -range 0x00010000 -target_address_space [get_bd_addr_spaces microblaze_0/Data] [get_bd_addr_segs axi_gpio_0/S_AXI/Reg] -force + assign_bd_address -offset 0x40010000 -range 0x00010000 -target_address_space [get_bd_addr_spaces microblaze_0/Data] [get_bd_addr_segs axi_gpio_1/S_AXI/Reg] -force + assign_bd_address -offset 0x41200000 -range 0x00010000 -target_address_space [get_bd_addr_spaces microblaze_0/Data] [get_bd_addr_segs axi_intc_0/S_AXI/Reg] -force + assign_bd_address -offset 0x41C00000 -range 0x00010000 -target_address_space [get_bd_addr_spaces microblaze_0/Data] [get_bd_addr_segs axi_timer_0/S_AXI/Reg] -force + assign_bd_address -offset 0x40600000 -range 0x00010000 -target_address_space [get_bd_addr_spaces microblaze_0/Data] [get_bd_addr_segs axi_uartlite_0/S_AXI/Reg] -force + assign_bd_address -offset 0x00000000 -range 0x00008000 -target_address_space [get_bd_addr_spaces microblaze_0/Data] [get_bd_addr_segs microblaze_0_local_memory/dlmb_bram_if_cntlr/SLMB/Mem] -force + assign_bd_address -offset 0x00000000 -range 0x00008000 -target_address_space [get_bd_addr_spaces microblaze_0/Instruction] [get_bd_addr_segs microblaze_0_local_memory/ilmb_bram_if_cntlr/SLMB/Mem] -force + + + # Restore current instance + current_bd_instance $oldCurInst + + validate_bd_design + save_bd_design +} +# End of create_root_design() + + +################################################################## +# MAIN FLOW +################################################################## + +create_root_design "" + + diff --git a/hw/src/constraints/.keep b/hw/src/constraints/.keep new file mode 100644 index 0000000..e69de29 diff --git a/hw/src/hdl/.keep b/hw/src/hdl/.keep new file mode 100644 index 0000000..e69de29 diff --git a/hw/src/ip/.keep b/hw/src/ip/.keep new file mode 100644 index 0000000..e69de29 diff --git a/hw/src/other/.keep b/hw/src/other/.keep new file mode 100644 index 0000000..e69de29 diff --git a/project_info.tcl b/project_info.tcl index 9588e57..136326b 100644 --- a/project_info.tcl +++ b/project_info.tcl @@ -1,9 +1,19 @@ # This is an automatically generated file used by digilent_vivado_checkout.tcl to set project options -proc set_digilent_project_properties {proj_name} { +proc set_project_properties_post_create_project {proj_name} { set project_obj [get_projects $proj_name] - set_property "part" "xc7a35tcpg236-1" $project_obj - set_property "board_part" "digilentinc.com:cmod_a7-35t:part0:1.1" $project_obj - set_property "default_lib" "xil_defaultlib" $project_obj - set_property "simulator_language" "Mixed" $project_obj - set_property "target_language" "Verilog" $project_obj + set_property "part" "xc7a35tcpg236-1" $project_obj + set_property "board_part" "digilentinc.com:cmod_a7-35t:part0:1.1" $project_obj + set_property "default_lib" "xil_defaultlib" $project_obj + set_property "simulator_language" "Mixed" $project_obj + set_property "target_language" "Verilog" $project_obj +} + +proc set_project_properties_pre_add_repo {proj_name} { + set project_obj [get_projects $proj_name] + # default nothing +} + +proc set_project_properties_post_create_runs {proj_name} { + set project_obj [get_projects $proj_name] + # default nothing } diff --git a/scripts b/scripts new file mode 160000 index 0000000..ed11b88 --- /dev/null +++ b/scripts @@ -0,0 +1 @@ +Subproject commit ed11b88630aca2ae294feac832ff430dca5c74b4 diff --git a/sw/scripts/LICENSE b/sw/scripts/LICENSE new file mode 100644 index 0000000..1992fe4 --- /dev/null +++ b/sw/scripts/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Digilent + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/sw/scripts/README.md b/sw/scripts/README.md new file mode 100644 index 0000000..6a128b8 --- /dev/null +++ b/sw/scripts/README.md @@ -0,0 +1,61 @@ +# digilent-vitis-scripts +This repository contains a set of scripts for managing Vitis workspaces with git. + +---- +## Quick Checkout Guide + +When cloning this repository, use the command `git clone --recursive ` to pick up any submodules this repository may use to bring in additional source files. Alternatively initialize and update the repository's submodules after cloning (`git submodule update --init` within the repo directory). + +Some Digilent Github repositories also require that you check out a specific demo branch. Whenever checking out a demo branch, submodules should be reupdated and reinitialized (`git submodule update --init`, as above). + +When launching Vitis, whether through Vivado's *Tools* menu, or on its own, the Vitis workspace should be set to the repository's sw/ws folder. + +The scripts present in this repository can be run through the use of the Xilinx Software Command-Line Tool (XSCT), which is built into Vitis. This tool can be opened within the Vitis GUI through the *Xilinx > XSCT Console* option in the menu bar at the top of the window. Upon launch, XSCT's current working directory is set to the Vitis install directory. To recreate the workspace, enter the following command into the XSCT Console: + +`source [getws]/../src/checkout.tcl` + +This process will populate the workspace with projects containing sources from the parent repository's src folder, configure those projects, and fully build them. This may take several minutes to fully complete. When the script is finished running, the `xsct%` prompt wil reappear in the tan XSCT Process pane. From this point, the demo can be programmed onto a board, sources can be viewed, and modified, as desired. + +**Note:** *The current working directory is irrelevant to the functionality of the scripts in this submodule.* + +---- +## Quick Checkin Guide + +**Important:** *The checkin.tcl script should generally only be used for the first time checking a project into version control. For further commits, new files should be manually copied into the repository's src directory. Application source files (and linker scripts) are soft-linked into the workspace upon checkout, so existing files do not need to be manually copied back. Modifications to project settings require that the corresponding scripts in the repository's src directory be edited.* + +This section assumes that you have already created a Vitis workspace containing one or more application projects. Some additional work may be required after the checkin script is completed, and it is important that you try the checkout process afterwards to ensure that all important settings are properly included. + +The checkin script has only been tested with standalone application projects at time of writing. + +To add this repository to a parent repository as a submodule, first open a terminal with access to git. If your parent repository does not yet have a `sw` subdirectory (or submodule), create one and cd into it. Adding the `scripts` path argument to the command is recommended in order to keep file paths short. + +`git submodule add https://github.com/Digilent/digilent-vitis-scripts scripts` + +Open your workspace in Vitis. Open the XSCT Console from within the Vitis GUI by selecting the *Xilinx > XSCT Console* option in the menu bar at the top of the window. To copy all relevant (local only!) source files into the parent repository's src directory and create the scripts used by checkout.tcl, run the following command: + +`source /checkin.tcl` + +This script will create a src directory in the same folder as the scripts submodule, and populate it as below: + +* checkout.tcl script and README file +* One folder per application project, containing the following: + * A src directory, containing the application project's local sources (from its src folder) and linker script. + * A #_standalone_app.tcl script, containing the XSCT commands required to recreate and configure the project. + * A #_build_app.tcl script, containing the XSCT commands required to build the project. +* One folder per (non-automatically generated) domain, containing the following: + * A #_standalone_bsp.tcl script containing the XSCT commands to recreate and configure the domain. +* One folder per hardware platform, containing the following: + * A #_hw_pf_xsa.tcl script, containing the XSCT commands required to recreate and configure the platform, using only the XSA as input. + * The XSA file describing the hardware specification that the software targets, exported from Vivado. + +Additionally, a gitignore file is created in the parent repository's sw directory. + +Note that the name of each folder is used in checkout to determine the name of the app/platform/domain it is used to create. + +The numeric prefixes for XSCT scripts are used to determine the order in which they are sourced during checkout (lowest to highest). Recommended: 0-9 for hardware platform, 20-29 for bsp, 40-49 for app creation. Build scripts are recommended to use > 100. + +As mentioned above, you MUST test the checkout process and check the generated scripts to ensure that all sources, project settings, and build configuration settings are correctly applied to the projects when someone else checks them out. + +The checkin script is *not* perfect, and manual intervention is likely to be required after the script is run. Edit the automatically generated scripts as needed, and double check your source files. + +---- diff --git a/sw/scripts/checkin.tcl b/sw/scripts/checkin.tcl new file mode 100644 index 0000000..077eddc --- /dev/null +++ b/sw/scripts/checkin.tcl @@ -0,0 +1,421 @@ +# Run this script extract source files from a Vitis workspace to the src/ directory +# If ::create_path global variable is set, the source files are created there instead of src/ + +set script [info script] +set script_dir [file normalize [file dirname $script]] + +puts "INFO: Running $script." + +if {[info exists ::create_path]} { + set dest_dir $::create_path +} else { + set dest_dir [file normalize $script_dir/../src] +} + +if {[info exists ::debug_prevent_fileio]} { + set debug_prevent_fileio $::debug_prevent_fileio +} else { + set debug_prevent_fileio 0 +} + +puts "INFO: Targeting $dest_dir for export" +set var_overwrite_ok [dict create] + +proc yes_or_no {msg} { + while 1 { + puts -nonewline $msg + flush stdout; + if {[gets stdin input] < 0 && [eof stdin]} { + return -code error "end of file detected" + } + if { [regexp -nocase -line -- {^(y|n|yes|no)$} $input match] } { + break + } + } + return $match +} +proc overwrite_ok {} { + global var_overwrite_ok; + global dest_dir; + if { ![dict exists $var_overwrite_ok "answer"] } { + puts -nonewline "WARNING: Existing resources in $dest_dir will be overwritten." + set input [yes_or_no "Continue? (y/n):"] + if { [string equal -nocase -length 1 $input "y"] } { + dict set var_overwrite_ok "answer" true + } else { + dict set var_overwrite_ok "answer" false + } + } + return [dict get $var_overwrite_ok "answer"] +} + +# If workspace is not set, guess and confirm with the user +if { [getws] eq "" } { + set ws_dir [file normalize $script_dir/../ws] + puts -nonewline "WARNING: Workspace is not set. I can try checking in the workspace from $ws_dir. " + set input [yes_or_no "Continue? (y/n):"] + if { [string equal -nocase -length 1 $input "n"] } { + return -code ok + } + setws $ws_dir +} + +# Do the hardware platforms +set pf_names {} +if { [catch {platform list}] == 0 } { + # -dict is undocumented but got it from Xilinx support + set pfs [platform list -dict] + foreach pf $pfs { + lappend pf_names [dict get $pf Name] + } +} +puts "INFO: Found the following platform projects: $pf_names." + +foreach pf $pf_names { + if { [file exists $dest_dir/$pf/] } { + if { ![overwrite_ok] } { + puts "INFO: Ignoring [file normalize $dest_dir/$pf/] since already exists." + continue; + } + } else { + file mkdir $dest_dir/$pf + } + # For some reason it needs to be made active for report to work + platform active $pf + set pf_dest [file normalize $dest_dir/$pf/] + # Get the xsa + set xsa [file normalize [dict get [platform report -dict $pf] {hw spec}]] + set pf_subscript [file normalize $pf_dest/5_hw_pf_xsa.tcl] + + if {$debug_prevent_fileio == 0} { + # Check if xsa is linked from src already, copy if not + if { [file dirname $xsa] ne $pf_dest } { + file copy -force -- "$xsa" $pf_dest + } + file copy -force -- $script_dir/sub/hw_pf_xsa.tcl "$pf_subscript" + set fid [open "$pf_subscript" a] + } else { + puts "TRACE: file copy -force -- \"$xsa\" $pf_dest" + puts "TRACE: file copy -force -- $script_dir/sub/hw_pf_xsa.tcl \"$pf_subscript\"" + set fid stdout + } + + catch { + # Export platform config + puts $fid "\n" + puts $fid "platform config -extra-compiler-flags fsbl \"[platform config -extra-compiler-flags fsbl]\"" + puts $fid "platform config -extra-linker-flags fsbl \"[platform config -extra-linker-flags fsbl]\"" + puts $fid "platform config -extra-compiler-flags pmufw \"[platform config -extra-compiler-flags pmufw]\"" + puts $fid "platform config -extra-linker-flags pmufw \"[platform config -extra-linker-flags pmufw]\"" + } result options + if {$debug_prevent_fileio == 0} { + close $fid + } + return -options $options $result + + # Do the domains + set domain_names {} + if { [catch {domain list}] == 0 } { + # -dict is undocumented but got it from Xilinx support + set domains [domain list -dict] + foreach d $domains { + set d_name [dict get $d {Name}] + # Get domain properties + if { [string first "Auto Generated" [dict get [domain report -dict $d_name] {description}]] >= 0 } { + puts "INFO: Skipping $d_name, because it is auto-generated." + continue; + } + set os [dict get [domain report -dict $d_name] {os}] + if { $os ne "standalone" } { + puts "INFO: Skipping $d_name, because $os OS is not supported." + continue; + } + lappend domain_names $d_name + } + } + if {[llength $domain_names] != 0} {puts "INFO: Found the following domains : $domain_names."} + + foreach d $domain_names { + if { [file exists $dest_dir/$d/] } { + if { ![overwrite_ok] } { + puts "INFO: Ignoring [file normalize $dest_dir/$d/] since already exists." + continue; + } + } else { + file mkdir $dest_dir/$d + } + # For some reason it needs to be made active + domain active $d + + set d_subscript $dest_dir/$d/25_standalone_bsp.tcl + puts "INFO: Generating $d_subscript." + + if {$debug_prevent_fileio == 0} { + set dfid [open $d_subscript w] + } else { + set dfid stdout + } + set sfid [open $script_dir/sub/standalone_bsp.tcl r] + catch { + # Get domain properties + set proc [dict get [domain report -dict $d] {processor}] + set var_map [list $proc \ + ] + # Copy the subcript while replacing variables + while { [gets $sfid line] >= 0 } { + puts $dfid [string map $var_map $line] + } + # Only SOME of the config params possible + set bsp_configs {\ + clocking\ + enable_sw_intrusive_profiling\ + hypervisor_guest\ + lockstep_mode_debug\ + microblaze_exceptions\ + predecode_fpu_exceptions\ + profile_timer\ + sleep_timer\ + stdin\ + stdout\ + ttc_select_cntr\ + zynqmp_fsbl_bsp\ + archiver\ + assembler\ + compiler\ + compiler_flags\ + exec_mode\ + extra_compiler_flags\ + } + + foreach c $bsp_configs { + set err [catch {set val [bsp config $c]}] + if {$err != 0} { + puts "WARNING: BSP config parameter $c cannot be read from domain $d" + } else { + puts $dfid "bsp config $c \"$val\"" + } + } + + } result options + if {$debug_prevent_fileio == 0} { + close $dfid + } + close $sfid + return -options $options $result + } +} + +# Do the applications +set app_names "" +if { [catch {app list}] != 0 } { + return -code error "ERROR: Workspace contains no applications" +} +set apps [app list -dict] +foreach a $apps { + puts $a + lappend app_names [dict get $a Name] +} +puts "INFO: Found the following applications: $app_names" + +# For some reason, cannot look up sysproj association from app settings +# instead, build an app-keyed dict (lookup_sysproj) from the sysproj side +puts "INFO: Building sysproj lookup dict" +set sysprojs [sysproj list -dict] +foreach s $sysprojs { + set sysproj_name [dict get $s Name] + set sysproj_dict [sysproj report -name $sysproj_name -dict] + set sysproj_apps [dict get $sysproj_dict applications] + foreach a $sysproj_apps { + puts "INFO: app $a in sysproj $sysproj_name" + dict set lookup_sysproj $a $sysproj_name + } +} + +foreach app_name $app_names { + # Make src/app directory + if {$debug_prevent_fileio == 0} { + if { [file exists $dest_dir/$app_name/] } { + if { ![overwrite_ok] } { + puts "INFO: Ignoring [file normalize $dest_dir/$app_name/] since already exists." + continue; + } + } else { + file mkdir $dest_dir/$app_name + } + } else { + puts "TRACE: file mkdir $dest_dir/$app_name" + } + + # Get app create arguments + set app_dict [app report -dict $app_name] + set platform [dict get $app_dict "platform"] + set domain [dict get $app_dict "Domain"] + set lang "c"; # FIXME; cannot see an obvious way of automatically determining the language + puts "WARNING: ${app_name}'s language set to c; if c++ is required, please edit its standalone_app script" + if {$lang == "c"} { + set template "{Empty Application}" + } elseif {$lang == "c++"} { + set template "{Empty Application (C++)}" + } else { + return -code error "invalid language selection (must be c or c++): lang=$lang" + } + set sysproj [dict get $lookup_sysproj $app_name] + + # Copy build_app.tcl with no modifications + if {$debug_prevent_fileio == 0} { + file copy -force -- $script_dir/sub/build_app.tcl $dest_dir/$app_name/145_build_app.tcl + } else { + puts "TRACE: file copy -force -- $script_dir/sub/build_app.tcl $dest_dir/$app_name/145_build_app.tcl" + } + + # Copy standalone_app.tcl while replacing identifiers with the corresponding value + set var_map [list $domain \ + $platform \ + $lang \ + $sysproj ] + + set infile [open $script_dir/sub/standalone_app.tcl "r"] + if {$debug_prevent_fileio == 0} { + set outfile [open $dest_dir/$app_name/45_standalone_app.tcl "w"] + } else { + set outfile stdout + } + puts "INFO: Generating $dest_dir/$app_name/45_standalone_app.tcl" + + catch { + + while {[gets $infile s] >= 0} { + puts $outfile [string map $var_map $s] + } + + # Add configuration settings to the end of the file + set orig_config [app config -get -name $app_name "build-config"] + + foreach bc "Release Debug" { + app config -set -name $app_name "build-config" $bc + puts $outfile "app config -set -name \$app_name build-config $bc" + + # get/set configs that support -set + set value [app config -get -name $app_name "assembler-flags"] + puts $outfile "app config -set -name \$app_name assembler-flags \{$value\}" + + set value [app config -get -name $app_name "compiler-misc"] + puts $outfile "app config -set -name \$app_name compiler-misc \{$value\}" + + set value [app config -get -name $app_name "compiler-optimization"] + puts $outfile "app config -set -name \$app_name compiler-optimization \{$value\}" + + # -set not supported for define-compiler-symbols + # -get list is semicolon separated + # default no symbols means that each that is in current project can be added to the list to reproduce it + set symbols [app config -get -name $app_name "define-compiler-symbols"] + set symbols [split $symbols ";"] + foreach sym $symbols { + puts $outfile "app config -add -name \$app_name define-compiler-symbols \{$sym\}" + } + + # hardcode include-path to app src dir + puts $outfile "app config -add -name \$app_name include-path \$script_dir/src" + + # -set not supported for libraries + # -get list is semicolon separated + # default no libs means that each that is in current project can be added to the list to reproduce it + set libs [app config -get -name $app_name "libraries"] + set libs [split $libs ";"] + foreach lib $libs { + puts $outfile "app config -add -name \$app_name libraries $lib" + } + + # library-search-path not implemented; consider adding dedicated folders as in repo/vivado-library, repo/local + puts "WARNING: ${app_name} ${bc}'s library-search-path config will not be set by checkout" + + # hardcode linker-script link to app src dir + puts $outfile "app config -set -name \$app_name linker-script \$script_dir/src/lscript.ld" + + # -set not supported for undef-compiler-symbols + set symbols [app config -get -name $app_name "undef-compiler-symbols"] + set symbols [split $symbols ";"] + foreach sym $symbols { + puts $outfile "app config -add -name \$app_name undef-compiler-symbols $sym" + } + } + + app config -set -name $app_name "build-config" $orig_config + + puts "WARNING: application configs written to checkout script" + puts " the following settings must be manually added if non-default:" + puts " include-path (other than app src directory)" + puts " library-search-path" + + set appsrc_path [getws]/$app_name/src + if {$debug_prevent_fileio == 0} { + if {[file exists $dest_dir/$app_name/src] == 0} { + file copy -force -- $appsrc_path $dest_dir/$app_name + } else { + puts "WARNING: $dest_dir/$app_name/src already exists; cannot copy source directory" + } + } else { + puts "file copy -force -- $appsrc_path $dest_dir/$app_name" + } + puts "INFO: application sources placed in $appsrc_path copied to repo /src directory" + puts "WARNING: non-local sources not copied! Double-check that all sources are included in" + puts " version control and are soft-linked into the project/s on checkout" + } result options + + close $infile + # don't close stdout + if {$debug_prevent_fileio == 0} { + close $outfile + } + return -options $options $result +} + +# When all sources are checked into src/, copy checkout script and README too +if {$debug_prevent_fileio == 0} { + file copy -force -- [file normalize $script_dir/checkout.tcl] $dest_dir/ + file copy -force -- [file normalize $script_dir/README.md] [file normalize $dest_dir/] + # Attempt to query git HEAD hash + if { [catch { set fid [open "|git -C \"$script_dir\" rev-parse HEAD" r] } errmsg] } { + puts "WARNING: $errmsg" + puts "WARNING: git command cannot be found (not in PATH?), so could not append $dest_dir/README.md with script versioning info." + } elseif { [gets $fid hash] eq -1 } { + puts "WARNING: git error so could not append $dest_dir/README.md with script versioning info." + } else { + set dfid [open [file normalize $dest_dir/README.md] a] + catch { + puts $dfid "\nThis README.md was created by the following commit hash:\n$hash" + } result options + close $dfid + close $fid + return -options $options $result + } +} + +# Copy cleanup scripts to ws/, which is the default destination for checkout.tcl +if {$debug_prevent_fileio == 0} { + if {[file exists $dest_dir/../ws] == 0} { + file mkdir $dest_dir/../ws + } + file copy -force -- [file normalize $script_dir/sub/cleanup._sh] [file normalize $dest_dir/../ws/cleanup.sh] + file copy -force -- [file normalize $script_dir/sub/cleanup._cmd] [file normalize $dest_dir/../ws/cleanup.cmd] +} + +# Copy template gitignore +if {$debug_prevent_fileio == 0} { + set gitignore [file normalize $dest_dir/../.gitignore] + if {[file exists $gitignore] == 0} { + set copy_ok 1 + } else { + set input [yes_or_no "WARNING: $gitignore exists, overwrite it? (y/n):"] + if { [string equal -nocase -length 1 $input "n"] } { + set copy_ok 0 + } else { + set copy_ok 1 + } + } + if {$copy_ok} { + file copy -force -- [file normalize $script_dir/sub/template.gitignore] $gitignore + } +} + +puts "INFO: Checked in workspace [getws] to $dest_dir" diff --git a/sw/scripts/checkout.tcl b/sw/scripts/checkout.tcl new file mode 100644 index 0000000..16fe7ec --- /dev/null +++ b/sw/scripts/checkout.tcl @@ -0,0 +1,102 @@ +# Run this script to create the Vitis workspace in the /ws/ sub-directory +# If ::create_path global variable is set, the project is created under that path instead of ws/ + +set script [info script] +set script_dir [file normalize [file dirname $script]] + +puts "INFO: Running $script." + +if {[info exists ::create_path]} { + set dest_dir $::create_path +} else { + set dest_dir [file normalize $script_dir/../ws] +} + +set src_dir [file normalize $script_dir/../src] + +puts "INFO: Targeting $dest_dir for workspace creation." + +# Check workspace for existing sub-dirs +if { [llength [glob -nocomplain -types d $dest_dir/*]] != 0 } { + # If the workspace is already set to the destination directory + if { [file normalize [getws]] == [file normalize $dest_dir] } { + # Check if the workspace is empty, which it will be if Vitis is launched in an empty directory + if { [catch {app list} ] == 0 || [catch {platform list} ] == 0 || [catch {domain list} ] == 0 || [catch {library list} ] == 0 } { + puts "WARNING: workspace is not empty. Close Vitis or XSCT to relinquish control and run the cleanup scripts. Re-run create_workspace.tcl afterwards." + flush stdout; + return -code error "Workspace already exists and needs to be closed first" + } + } else { + puts -nonewline "WARNING: workspace is not empty. Continuing might cause naming conflicts and workspace creation to fail. Recommend running the cleanup scripts before continuing. Continue? (y/n):" + while 1 { + flush stdout; + if {[gets stdin input] < 0 && [eof stdin]} { + return -code error "end of file detected" + } + if { [regexp -nocase -line -- {^(y|n|yes|no)$} $input] } { + break + } + puts -nonewline "Continue? (y/n):" + } + if { [string equal -nocase -length 1 $input "n"] } { + return -code ok + } + } +} + +# Change directory +set popd [pwd] +cd $dest_dir + +catch { + setws -switch $dest_dir + + # Get all *.tcl files in src_dir recursively and sort them by integer prefix + proc deep_traverse {base glob} { + set files [list] + + foreach d [glob -nocomplain -types d -directory $base *] { + lappend files {*}[deep_traverse $d $glob] + } + foreach f [glob -nocomplain -types f -directory $base -- $glob] { + lappend files [file normalize $f] + } + return $files + } + + proc sort_by_fileprefix {file1 file2} { + set i1 [scan [file tail $file1] "%d"] + set i2 [scan [file tail $file2] "%d"] + + return [expr $i1 > $i2] + } + + set scripts [deep_traverse $src_dir "*.tcl"] + # Self should be there + set selfs [lsearch -all $scripts [file normalize $script]] + if { [llength $selfs] eq 0 } { + return -code error "ERROR: Self not found while deep searching $src_dir" + } + # Remove all instances of self to avoid recursive call below + foreach idx $selfs { + set scripts [lreplace $scripts $idx $idx] + } + # Order by integer prefix + set ordered_scripts [lsort -command sort_by_fileprefix $scripts] + + puts "INFO: Found the following subscripts:" + foreach s $ordered_scripts { + puts $s + } + + # Source each subscript in order + foreach s $ordered_scripts { + source $s + } + +} result options + +puts "Changing back working dir to: $popd" +cd $popd + +return -options $options $result diff --git a/sw/scripts/sub/build_app.tcl b/sw/scripts/sub/build_app.tcl new file mode 100644 index 0000000..321ec0e --- /dev/null +++ b/sw/scripts/sub/build_app.tcl @@ -0,0 +1,11 @@ +# This script will build the application named after the script directory +# Workspace should be set externally + +set script [info script] +set script_dir [file normalize [file dirname $script]] + +puts "INFO: Running $script" + +set app_name [file tail $script_dir] + +app build -name $app_name \ No newline at end of file diff --git a/sw/scripts/sub/cleanup._cmd b/sw/scripts/sub/cleanup._cmd new file mode 100644 index 0000000..a2edfad --- /dev/null +++ b/sw/scripts/sub/cleanup._cmd @@ -0,0 +1,24 @@ +@echo off +rem save current working directory +pushd %~dp0 + +rem delete all files from subfolders +for /d /r %%i in (*) do del /f /q %%i\* +rem delete all subfolders +for /d %%i in (*) do rd /S /Q %%i + +rem unmark read only from all files +attrib -R .\* /S + +rem mark read only those we wish to keep +attrib +R .\cleanup.sh +attrib +R .\cleanup.cmd + +rem delete all non read-only +del /Q /A:-R .\* + +rem unmark read-only +attrib -R .\* + +rem restore original working directory +popd \ No newline at end of file diff --git a/sw/scripts/sub/cleanup._sh b/sw/scripts/sub/cleanup._sh new file mode 100644 index 0000000..df1dd41 --- /dev/null +++ b/sw/scripts/sub/cleanup._sh @@ -0,0 +1,14 @@ +# This script is useful for cleaning up the 'project' +# directory of a Digilent Vivado-project git repository +### +# Run the following command to change permissions of +# this 'cleanup' file if needed: +# chmod u+x cleanup.sh +### +script_dir=$(dirname ${BASH_SOURCE[0]}) +# Remove directories/subdirectories +find $script_dir -mindepth 1 -type d -exec rm -rf {} + +# Remove any other files than: +find $script_dir -type f ! -name 'cleanup.sh' \ + ! -name 'cleanup.cmd' \ + -exec rm -rf {} + diff --git a/sw/scripts/sub/hw_pf_xsa.tcl b/sw/scripts/sub/hw_pf_xsa.tcl new file mode 100644 index 0000000..29d0f72 --- /dev/null +++ b/sw/scripts/sub/hw_pf_xsa.tcl @@ -0,0 +1,15 @@ +# This script will take the first *.xsa file near it and create a new platform based on it +# Workspace should be set externally + +set script [info script] +set script_dir [file normalize [file dirname $script]] + +puts "INFO: Running $script" + +set hw_src [lindex [glob -nocomplain $script_dir/*.xsa] 0] + +puts "INFO: Found $hw_src" + +set hw_name [file tail $script_dir] + +platform create -name "$hw_name" -hw "$hw_src" \ No newline at end of file diff --git a/sw/scripts/sub/standalone_app.tcl b/sw/scripts/sub/standalone_app.tcl new file mode 100644 index 0000000..3921c10 --- /dev/null +++ b/sw/scripts/sub/standalone_app.tcl @@ -0,0 +1,39 @@ +# This script will create an application named after the script directory +# based on the C "Empty Application" template and for a specific processor +# It imports all source files from the src subdirectory as LINKS. +# BUG 2020.1: linker script imported as link won't build, import by setting +# linker-script app config as a workaround. +# It also sets some C/C++ build settings +# Workspace should be set externally + +set script [info script] +set script_dir [file normalize [file dirname $script]] + +puts "INFO: Running $script" + +set app_name [file tail $script_dir] + +# Variables created by checkin.tcl +set lang "" +set domain "" +set platform "" +set sysproj "" + +# Handle dependent variables +if {$lang == "c"} { + set template "Empty Application" +} elseif {$lang == "c++"} { + set template "Empty Application (C++)" +} else { + return -code error "invalid language selection in [file tail $script]; $lang should be c or c++" +} + + +# unused `app create` arguments: +# -os, -arch, and -proc are inferred from -domain? +# -hw conflicts with -platform usage +app create -name $app_name -lang $lang -template $template -domain $domain -platform $platform -sysproj $sysproj + +importsources -name $app_name -path $script_dir/src -soft-link + +# Set project settings per build configuration (handled by checkin) \ No newline at end of file diff --git a/sw/scripts/sub/standalone_bsp.tcl b/sw/scripts/sub/standalone_bsp.tcl new file mode 100644 index 0000000..f6977aa --- /dev/null +++ b/sw/scripts/sub/standalone_bsp.tcl @@ -0,0 +1,18 @@ +# This script will create a standalone domain for a processor and its architecture +# Workspace should be set externally + +set script [info script] +set script_dir [file normalize [file dirname $script]] + +puts "INFO: Running $script" + +set domain_name [file tail $script_dir] + +# Modify these for custom domain/BSP settings +set arch "32-bit" +set os "standalone" +set proc "" + +domain create -name $domain_name -proc $proc -arch $arch -os $os + +# Customize BSP, this replaces *.mss file diff --git a/sw/scripts/sub/template.gitignore b/sw/scripts/sub/template.gitignore new file mode 100644 index 0000000..0335111 --- /dev/null +++ b/sw/scripts/sub/template.gitignore @@ -0,0 +1,5 @@ +# ignore everything in workspace dir +ws/* +# except the cleanup scripts +!ws/cleanup.cmd +!ws/cleanup.sh \ No newline at end of file diff --git a/sw/sdk/.keep b/sw/sdk/.keep new file mode 100644 index 0000000..e69de29 diff --git a/sw/sdk/appsrc/intc/intc.c b/sw/sdk/appsrc/intc/intc.c new file mode 100644 index 0000000..cb27ebd --- /dev/null +++ b/sw/sdk/appsrc/intc/intc.c @@ -0,0 +1,96 @@ +/****************************************************************************** + * @file iic.c + * Interrupt system initialization. + * + * @author Elod Gyorgy + * + * @date 2015-Jan-3 + * + * @copyright + * (c) 2015 Copyright Digilent Incorporated + * All Rights Reserved + * + * This program is free software; distributed under the terms of BSD 3-clause + * license ("Revised BSD License", "New BSD License", or "Modified BSD License") + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name(s) of the above-listed copyright holder(s) nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * @desciption + * Contains interrupt controller initialization function. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who          Date     Changes
+ * ----- ------------ ----------- -----------------------------------------------
+ * 1.00  Elod Gyorgy  2015-Jan-3 First release
+ *
+ * 
+ * + *****************************************************************************/ + +#include "intc.h" +#include "xparameters.h" + +#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID + +XStatus fnInitInterruptController(XIntc *psIntc) +{ + // Init driver instance + RETURN_ON_FAILURE(XIntc_Initialize(psIntc, INTC_DEVICE_ID)); + + // Start interrupt controller + RETURN_ON_FAILURE(XIntc_Start(psIntc, XIN_REAL_MODE)); + + Xil_ExceptionInit(); + // Register the interrupt controller handler with the exception table. + // This is in fact the ISR dispatch routine, which calls our ISRs + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, + (Xil_ExceptionHandler)XIntc_InterruptHandler, + psIntc); + Xil_ExceptionEnable(); + + return XST_SUCCESS; +} + +/* + * This function enables interrupts and connects interrupt service routines declared in + * an interrupt vector table + */ +void fnEnableInterrupts(XIntc *psIntc, const ivt_t *prgsIvt, unsigned int csIVectors) +{ + unsigned int isIVector; + + Xil_AssertVoid(psIntc != NULL); + Xil_AssertVoid(psIntc->IsReady == XIL_COMPONENT_IS_READY); + + /* Hook up interrupt service routines from IVT */ + for (isIVector = 0; isIVector < csIVectors; isIVector++) + { + XIntc_Connect(psIntc, prgsIvt[isIVector].id, prgsIvt[isIVector].handler, prgsIvt[isIVector].pvCallbackRef); + + /* Enable the interrupt vector at the interrupt controller */ + XIntc_Enable(psIntc, prgsIvt[isIVector].id); + } +} diff --git a/sw/sdk/appsrc/intc/intc.h b/sw/sdk/appsrc/intc/intc.h new file mode 100644 index 0000000..1ab5b7c --- /dev/null +++ b/sw/sdk/appsrc/intc/intc.h @@ -0,0 +1,75 @@ +/****************************************************************************** + * @file intc.h + * Interrupt system initialization. + * + * @author Elod Gyorgy + * + * @date 2015-Jan-3 + * + * @copyright + * (c) 2015 Copyright Digilent Incorporated + * All Rights Reserved + * + * This program is free software; distributed under the terms of BSD 3-clause + * license ("Revised BSD License", "New BSD License", or "Modified BSD License") + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name(s) of the above-listed copyright holder(s) nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * @desciption + * Contains interrupt controller initialization function. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who          Date     Changes
+ * ----- ------------ ----------- -----------------------------------------------
+ * 1.00  Elod Gyorgy  2015-Jan-3 First release
+ *
+ * 
+ * + *****************************************************************************/ + +#ifndef INTC_H_ +#define INTC_H_ + +#include "xstatus.h" +#include "xintc.h" + + +#define RETURN_ON_FAILURE(x) if ((x) != XST_SUCCESS) return XST_FAILURE; + +/* + * Structure for interrupt id, handler and callback reference + */ +typedef struct { + u8 id; + XInterruptHandler handler; + void *pvCallbackRef; +} ivt_t; + +XStatus fnInitInterruptController(XIntc *psIntc); +void fnEnableInterrupts(XIntc *psIntc, const ivt_t *prgsIvt, unsigned int csIVectors); + + +#endif /* INTC_H_ */ diff --git a/sw/sdk/appsrc/lscript.ld b/sw/sdk/appsrc/lscript.ld new file mode 100644 index 0000000..619653c --- /dev/null +++ b/sw/sdk/appsrc/lscript.ld @@ -0,0 +1,213 @@ +/*******************************************************************/ +/* */ +/* This file is automatically generated by linker script generator.*/ +/* */ +/* Version: */ +/* */ +/* Copyright (c) 2010 Xilinx, Inc. All rights reserved. */ +/* */ +/* Description : MicroBlaze Linker Script */ +/* */ +/*******************************************************************/ + +_STACK_SIZE = DEFINED(_STACK_SIZE) ? _STACK_SIZE : 0x400; +_HEAP_SIZE = DEFINED(_HEAP_SIZE) ? _HEAP_SIZE : 0x0; + +/* Define Memories in the system */ + +MEMORY +{ + microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr : ORIGIN = 0x50, LENGTH = 0x7FB0 + axi_emc_0_S_AXI_MEM0_BASEADDR : ORIGIN = 0x60000000, LENGTH = 0x2000000 +} + +/* Specify the default entry point to the program */ + +ENTRY(_start) + +/* Define the sections, and where they are mapped in memory */ + +SECTIONS +{ +.vectors.reset 0x0 : { + KEEP (*(.vectors.reset)) +} + +.vectors.sw_exception 0x8 : { + KEEP (*(.vectors.sw_exception)) +} + +.vectors.interrupt 0x10 : { + KEEP (*(.vectors.interrupt)) +} + +.vectors.hw_exception 0x20 : { + KEEP (*(.vectors.hw_exception)) +} + +.text : { + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +.init : { + KEEP (*(.init)) +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +.fini : { + KEEP (*(.fini)) +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +.ctors : { + __CTOR_LIST__ = .; + ___CTORS_LIST___ = .; + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE(*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + __CTOR_END__ = .; + ___CTORS_END___ = .; +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +.dtors : { + __DTOR_LIST__ = .; + ___DTORS_LIST___ = .; + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE(*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + PROVIDE(__DTOR_END__ = .); + PROVIDE(___DTORS_END___ = .); +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +.rodata : { + __rodata_start = .; + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + __rodata_end = .; +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +.sdata2 : { + . = ALIGN(8); + __sdata2_start = .; + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + . = ALIGN(8); + __sdata2_end = .; +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +.sbss2 : { + __sbss2_start = .; + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + __sbss2_end = .; +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +.data : { + . = ALIGN(4); + __data_start = .; + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + __data_end = .; +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +.got : { + *(.got) +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +.got1 : { + *(.got1) +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +.got2 : { + *(.got2) +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +.eh_frame : { + *(.eh_frame) +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +.jcr : { + *(.jcr) +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +.gcc_except_table : { + *(.gcc_except_table) +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +.sdata : { + . = ALIGN(8); + __sdata_start = .; + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + __sdata_end = .; +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +.sbss (NOLOAD) : { + . = ALIGN(4); + __sbss_start = .; + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + . = ALIGN(8); + __sbss_end = .; +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +.tdata : { + __tdata_start = .; + *(.tdata) + *(.tdata.*) + *(.gnu.linkonce.td.*) + __tdata_end = .; +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +.tbss : { + __tbss_start = .; + *(.tbss) + *(.tbss.*) + *(.gnu.linkonce.tb.*) + __tbss_end = .; +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +.bss (NOLOAD) : { + . = ALIGN(4); + __bss_start = .; + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +_SDA_BASE_ = __sdata_start + ((__sbss_end - __sdata_start) / 2 ); + +_SDA2_BASE_ = __sdata2_start + ((__sbss2_end - __sdata2_start) / 2 ); + +/* Generate Stack and Heap definitions */ + +.heap (NOLOAD) : { + . = ALIGN(8); + _heap = .; + _heap_start = .; + . += _HEAP_SIZE; + _heap_end = .; +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +.stack (NOLOAD) : { + _stack_end = .; + . += _STACK_SIZE; + . = ALIGN(8); + _stack = .; + __stack = _stack; +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +_end = .; +} + diff --git a/sw/sdk/appsrc/memory_config.h b/sw/sdk/appsrc/memory_config.h new file mode 100644 index 0000000..14c411d --- /dev/null +++ b/sw/sdk/appsrc/memory_config.h @@ -0,0 +1,47 @@ +/****************************************************************************** +* +* Copyright (C) 2008 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#ifndef __MEMORY_CONFIG_H_ +#define __MEMORY_CONFIG_H_ + +struct memory_range_s { + char *name; + char *ip; + unsigned base; + unsigned size; +}; + +/* generated memory ranges defined in memory_ranges_g.c */ +extern struct memory_range_s memory_ranges[]; +extern int n_memory_ranges; + +#endif diff --git a/sw/sdk/appsrc/memory_config_g.c b/sw/sdk/appsrc/memory_config_g.c new file mode 100644 index 0000000..a142f31 --- /dev/null +++ b/sw/sdk/appsrc/memory_config_g.c @@ -0,0 +1,10 @@ +/* This file is automatically generated based on your hardware design. */ +#include "memory_config.h" +#include "xparameters.h" + +struct memory_range_s memory_ranges[] = { + /* microblaze_0_local_memory_dlmb_bram_if_cntlr memory will not be tested since application resides in the same memory */ + {"Cellular Ram", "emc", XPAR_EMC_0_S_AXI_MEM0_BASEADDR, 524287} +}; + +int n_memory_ranges = 1; diff --git a/sw/sdk/appsrc/memorytest.c b/sw/sdk/appsrc/memorytest.c new file mode 100644 index 0000000..a337fe0 --- /dev/null +++ b/sw/sdk/appsrc/memorytest.c @@ -0,0 +1,209 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#include +#include "xparameters.h" +#include "xil_types.h" +#include "xstatus.h" +#include "xil_testmem.h" +#include "xgpio.h" +#include "microblaze_sleep.h" + +#include "platform.h" +#include "memory_config.h" + + +#include "intc/intc.h" +#include "userio/userio.h" + +static XIntc sIntc; + +/* + * memory_test.c: Test memory ranges present in the Hardware Design. + * + * This application runs with D-Caches disabled. As a result cacheline requests + * will not be generated. + * + * For MicroBlaze/PowerPC, the BSP doesn't enable caches and this application + * enables only I-Caches. For ARM, the BSP enables caches by default, so this + * application disables D-Caches before running memory tests. + */ + +/************************** Variable Definitions *****************************/ + +/* + * The following are declared globally so they are zeroed and so they are + * easily accessible from a debugger + */ + +XGpio Gpio1; /* The Instance of the GPIO Driver for Leds and buttons */ +#define LED_CHANNEL 1 +#define BTN_CHANNEL 2 +#define LED_MASK 0x03 +#define BTN_MASK 0x01 + +XGpio Gpio2; /* The Instance of the GPIO Driver for the RGB Leds */ +#define RGB_MASK 0x07 + +void putnum(unsigned int num); +//void xil_printf(char *ptr); + + + +static XTmrCtr sTmr; + +// interrupt vector table +const ivt_t ivt[] = { + // User I/O + {XPAR_AXI_INTC_0_AXI_TIMER_0_INTERRUPT_INTR, (XInterruptHandler)XTmrCtr_InterruptHandler, &sTmr} +}; + + +void test_memory_range(struct memory_range_s *range) { + XStatus status; + + /* This application uses xil_printf statements instead of xil_xil_printff/xil_printff + * to reduce the text size. + * + * The default linker script generated for this application does not have + * heap memory allocated. This implies that this program cannot use any + * routines that allocate memory on heap (xil_printff is one such function). + * If you'd like to add such functions, then please generate a linker script + * that does allocate sufficient heap memory. + */ + + xil_printf("Testing memory region: "); xil_printf(range->name); xil_printf("\n\r"); + xil_printf(" Memory Controller: "); xil_printf(range->ip); xil_printf("\n\r"); + xil_printf(" Base Address: 0x"); putnum(range->base); xil_printf("\n\r"); + xil_printf(" Size: 0x"); putnum(range->size); xil_printf (" bytes \n\r"); + + status = Xil_TestMem32((u32*)range->base, ((range->size)/32), 0xAAAA5555, XIL_TESTMEM_ALLMEMTESTS); + xil_printf(" 32-bit test: "); xil_printf(status == XST_SUCCESS? "PASSED!":"FAILED!"); xil_printf("\n\r"); + + status = Xil_TestMem16((u16*)range->base, ((range->size)/16), 0xAA55, XIL_TESTMEM_ALLMEMTESTS); + xil_printf(" 16-bit test: "); xil_printf(status == XST_SUCCESS? "PASSED!":"FAILED!"); xil_printf("\n\r"); + + status = Xil_TestMem8((u8*)range->base, ((range->size)/8), 0xA5, XIL_TESTMEM_ALLMEMTESTS); + xil_printf(" 8-bit test: "); xil_printf(status == XST_SUCCESS? "PASSED!":"FAILED!"); xil_printf("\n\r"); + +} + +int main() +{ + int i; + int Status = 0; + int leds = 0; + int rgb_col = 0; + int button = 0; + int last_button = 0; + + init_platform(); + + xil_printf("--Starting Memory Test Application--\n\r"); + xil_printf("NOTE: This application runs with D-Cache disabled."); + xil_printf("As a result, cacheline requests will not be generated\n\r"); + + for (i = 0; i < n_memory_ranges; i++) { + test_memory_range(&memory_ranges[i]); + } + + xil_printf("--Memory Test Application Complete--\n\r"); + + + //once past memory testing enter GPIO loop + Status = XGpio_Initialize(&Gpio1, XPAR_AXI_GPIO_0_DEVICE_ID); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + Status = XGpio_Initialize(&Gpio2, XPAR_AXI_GPIO_1_DEVICE_ID); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + //set leds to outputs and the button to an input + XGpio_SetDataDirection(&Gpio1, LED_CHANNEL, ~LED_MASK); + XGpio_SetDataDirection(&Gpio1, BTN_CHANNEL, BTN_MASK); + XGpio_SetDataDirection(&Gpio2, RGB_CHANNEL, ~RGB_MASK); + + // Initialize the interrupt controller + Status = fnInitInterruptController(&sIntc); + if(Status != XST_SUCCESS) { + xil_printf("\r\nError initializing interrupts"); + return XST_FAILURE; + } + + // Initializing User I/O GPIO driver + Status = fnInitUserIO(&Gpio2, &sTmr); + if(Status != XST_SUCCESS) { + xil_printf("\r\nError initializing User I/O"); + return XST_FAILURE; + } + + // Enable all interrupts in our interrupt vector table + // Make sure all driver instances using this IVT are initialized first + fnEnableInterrupts(&sIntc, &ivt[0], sizeof(ivt)/sizeof(ivt[0])); + + + while(1){ + //read button + button = XGpio_DiscreteRead(&Gpio1, BTN_CHANNEL); + //if it is 1 and the last press was zero then assign new leds + if(button == BTN_MASK && button != last_button){ + + last_button = button; + rgb_col ++; + rgb_col = rgb_col % 8; + leds ++; + leds = leds % 4; + switch(rgb_col){ //colors RGB + case 1: fnUpdateRgbsFromButtons(3);break; //red 0b011 + case 2: fnUpdateRgbsFromButtons(5);break; //green 0b101 + case 3: fnUpdateRgbsFromButtons(6);break; //blue 0b110 + case 4: fnUpdateRgbsFromButtons(4);break; //cyan 0b100 + case 5: fnUpdateRgbsFromButtons(2);break; //magenta 0b010 + case 6: fnUpdateRgbsFromButtons(1);break; //yellow 0b001 + case 7: fnUpdateRgbsFromButtons(0);break; //white 0b000 + case 0: fnUpdateRgbsFromButtons(7);break; //off 0b111 + } + XGpio_DiscreteWrite(&Gpio1, LED_CHANNEL, leds & LED_MASK); + xil_printf("\r\nButton Pressed"); + } + else + last_button = button; + + + } + + cleanup_platform(); + return 0; +} diff --git a/sw/sdk/appsrc/platform.c b/sw/sdk/appsrc/platform.c new file mode 100644 index 0000000..08539f3 --- /dev/null +++ b/sw/sdk/appsrc/platform.c @@ -0,0 +1,94 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#include "xparameters.h" +#include "xil_cache.h" + +#include "platform_config.h" + +#ifdef STDOUT_IS_16550 +#include "xuartns550_l.h" +#endif + +void +enable_caches() +{ +#ifdef __PPC__ + Xil_ICacheEnableRegion(XPAR_CACHEABLE_REGION_MASK); + // Do not enable caches for memory tests, this has pros and cons + // Pros - If caches are enabled, under certain configurations, there will be very few + // transactions to external memory + // Con - This might not generate a burst cacheline request + // Xil_DCacheEnableRegion(CACHEABLE_REGION_MASK); +#elif __MICROBLAZE__ +#ifdef XPAR_MICROBLAZE_USE_ICACHE + Xil_ICacheEnable(); +#endif +#ifdef XPAR_MICROBLAZE_USE_DCACHE + // See reason above for not enabling D Cache + // Xil_DCacheEnable(); +#endif +#elif __arm__ + // For ARM, BSP enables caches by default. +#endif +} + +void +disable_caches() +{ + Xil_DCacheDisable(); + Xil_ICacheDisable(); +} + +void +init_platform() +{ + enable_caches(); + +#ifdef __arm__ + // For ARM, BSP enables caches by default. Disable them here. + // See reason above for disabling D Cache + Xil_DCacheDisable(); +#endif + + /* if we have a uart 16550, then that needs to be initialized */ +#ifdef STDOUT_IS_16550 + XUartNs550_SetBaud(STDOUT_BASEADDR, XPAR_XUARTNS550_CLOCK_HZ, 9600); + XUartNs550_SetLineControlReg(STDOUT_BASEADDR, XUN_LCR_8_DATA_BITS); +#endif +} + +void +cleanup_platform() +{ + disable_caches(); +} diff --git a/sw/sdk/appsrc/platform.h b/sw/sdk/appsrc/platform.h new file mode 100644 index 0000000..e273e37 --- /dev/null +++ b/sw/sdk/appsrc/platform.h @@ -0,0 +1,41 @@ +/****************************************************************************** +* +* Copyright (C) 2008 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#ifndef __PLATFORM_H_ +#define __PLATFORM_H_ + +#include "platform_config.h" + +void init_platform(); +void cleanup_platform(); + +#endif diff --git a/sw/sdk/appsrc/platform_config.h b/sw/sdk/appsrc/platform_config.h new file mode 100644 index 0000000..70b9b1a --- /dev/null +++ b/sw/sdk/appsrc/platform_config.h @@ -0,0 +1,4 @@ +#ifndef __PLATFORM_CONFIG_H_ +#define __PLATFORM_CONFIG_H_ + +#endif diff --git a/sw/sdk/appsrc/userio/userio.c b/sw/sdk/appsrc/userio/userio.c new file mode 100644 index 0000000..b949da3 --- /dev/null +++ b/sw/sdk/appsrc/userio/userio.c @@ -0,0 +1,188 @@ +/****************************************************************************** + * @file userio.c + * + * @authors Elod Gyorgy + * + * @date 2015-Jan-03 + * + * @copyright + * (c) 2015 Copyright Digilent Incorporated + * All Rights Reserved + * + * This program is free software; distributed under the terms of BSD 3-clause + * license ("Revised BSD License", "New BSD License", or "Modified BSD License") + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name(s) of the above-listed copyright holder(s) nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * @desciption + * + * @note + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who          Date        Changes
+ * ----- ------------ ----------- --------------------------------------------
+ * 1.00  Elod Gyorgy  2015-Jan-03 First release
+ *
+ * 
+ * + *****************************************************************************/ + +#include +#include "xparameters.h" +#include "userio.h" + +/* + * The timer is used to generate a PWM signal for the RGB LEDs. + * the first timer is used for the PWM Period, the second for setting the PWM Pulse + */ +#define TMR_NUM_PERIOD 0 +#define TMR_NUM_PULSE 1 + +/* + * To achieve a 1 KHz PWM frequency, the Timer should count to 100,000 ticks, + * assuming the clock is 100 MHz (100,000,000/1,000/2). + */ +#define TMR_PERIOD_CNT 2000 + +/* + * This is the number of ticks to keep the pulse high. The duty cycle is + * TMR_PULSE_CNT/TMR_PERIOD_CNT + */ +#define TMR_PULSE_CNT 150 + +extern unsigned char u8UserIO; + +static u32 rgb_color; +const u32 rgb_colorarray[] = { + RGB_RED, + RGB_GREEN, + RGB_BLUE, + RGB_MAGENTA, + RGB_CYAN, + RGB_YELLOW, + RGB_WHITE, + RGB_OFF +}; + +//Yea, these globals are stupid, but I needed access to the input and output XGpios from the ISR, +//and this is simpler than defining a custom struct that contains both. --Sam +static XGpio *RGB_global; + +void fnUpdateLedsFromSwitches(); +void fnUpdateRgbsFromButtons(); + +XStatus fnInitUserIO(XGpio *Gpio2, XTmrCtr *psTmr) +{ + /* Initialize the GPIO driver. If an error occurs then exit */ + + /* + * Perform a self-test on the GPIO. This is a minimal test and only + * verifies that there is not any bus error when reading the data + * register + */ + + /* + * Setup direction register so the switches and buttons are inputs and the LED is + * an output of the GPIO + */ + + + RGB_global = Gpio2; +// +// fnUpdateLedsFromSwitches(); + rgb_color = RGB_OFF; + XGpio_DiscreteWrite(Gpio2, RGB_CHANNEL, 0); + + /* + * Enable the GPIO channel interrupts so that push button can be + * detected and enable interrupts for the GPIO device + */ + + /* + * Initialize timer for RGB LED PWMing + */ + RETURN_ON_FAILURE(XTmrCtr_Initialize(psTmr, XPAR_AXI_TIMER_0_DEVICE_ID)); + RETURN_ON_FAILURE(XTmrCtr_SelfTest(psTmr, TMR_NUM_PERIOD)); + RETURN_ON_FAILURE(XTmrCtr_SelfTest(psTmr, TMR_NUM_PULSE)); + + /* + * Setup the handler for the timer counter + */ + XTmrCtr_SetHandler(psTmr, fnUserIOTmrIsr, psTmr); + + /* + * Enable the interrupt of the timer counter so interrupts will occur + * and use auto reload mode such that the timer counter will reload + * itself automatically and continue repeatedly, without this option + * it would expire once only. Also count down + */ + XTmrCtr_SetOptions(psTmr, TMR_NUM_PERIOD, + XTC_INT_MODE_OPTION | XTC_AUTO_RELOAD_OPTION | XTC_DOWN_COUNT_OPTION); + /* + * The Pulse timer also uses the interrupt and counts down + */ + XTmrCtr_SetOptions(psTmr, TMR_NUM_PULSE, + XTC_INT_MODE_OPTION | XTC_DOWN_COUNT_OPTION); + + + XTmrCtr_SetResetValue(psTmr, TMR_NUM_PERIOD, TMR_PERIOD_CNT); + XTmrCtr_SetResetValue(psTmr, TMR_NUM_PULSE, TMR_PULSE_CNT); + + /* + * Start the timer counter. Interrupts will begin being triggered (at the + * timer layer). Don't start the pulse timer until in the ISR + */ + XTmrCtr_Start(psTmr, TMR_NUM_PERIOD); + + return XST_SUCCESS; +} + +void fnUpdateRgbsFromButtons(int rgb_col) +{ + rgb_color = rgb_col; +} + +/* + * Timer interrupt service routine + */ +void fnUserIOTmrIsr(void *CallBackRef, u8 TmrCtrNumber) +{ + XTmrCtr *psTmr = (XTmrCtr *)CallBackRef; + + + if (TmrCtrNumber == TMR_NUM_PERIOD) + { + + XTmrCtr_Start(psTmr, TMR_NUM_PULSE); + + XGpio_DiscreteWrite(RGB_global, RGB_CHANNEL, rgb_color); + } + else + { + XGpio_DiscreteWrite(RGB_global, RGB_CHANNEL, 7); + } +} + diff --git a/sw/sdk/appsrc/userio/userio.h b/sw/sdk/appsrc/userio/userio.h new file mode 100644 index 0000000..dfd3f5a --- /dev/null +++ b/sw/sdk/appsrc/userio/userio.h @@ -0,0 +1,93 @@ +/****************************************************************************** + * @file userio.h + * + * @authors Elod Gyorgy + * + * @date 2015-Jan-03 + * + * @copyright + * (c) 2015 Copyright Digilent Incorporated + * All Rights Reserved + * + * This program is free software; distributed under the terms of BSD 3-clause + * license ("Revised BSD License", "New BSD License", or "Modified BSD License") + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name(s) of the above-listed copyright holder(s) nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * @desciption + * + * @note + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who          Date        Changes
+ * ----- ------------ ----------- --------------------------------------------
+ * 1.00  Elod Gyorgy  2015-Jan-03 First release
+ *
+ * 
+ * + *****************************************************************************/ + +#ifndef USERIO_H_ +#define USERIO_H_ + +#include "xstatus.h" +#include "xgpio.h" +#include "xtmrctr.h" + +#define RGB_CHANNEL 1 /* Channel 2 of the output GPIO Device */ +#define SW_INTERRUPT XGPIO_IR_CH1_MASK /* Channel 1 Interrupt Mask */ +#define BTN_INTERRUPT XGPIO_IR_CH2_MASK /* Channel 2 Interrupt Mask */ + +//#define BTNU_MASK 0x0100 +//#define BTNR_MASK 0x0200 +//#define BTND_MASK 0x0400 +//#define BTNL_MASK 0x0800 +//#define BTNC_MASK 0x1000 +#define SWS_MASK 0x000F +#define BTNS_MASK 0x001F +#define RESET_MASK 0x0010 + +#define LEDS_MASK 0x00F +#define RGBS_MASK 0xFFF + +#define RETURN_ON_FAILURE(x) if ((x) != XST_SUCCESS) return XST_FAILURE; + +#define RGB_WHITE 0b000 +#define RGB_RED 0b011 +#define RGB_GREEN 0b101 +#define RGB_YELLOW 0b101 +#define RGB_CYAN 0b101 +#define RGB_MAGENTA 0b101 +#define RGB_BLUE 0b110 +#define RGB_OFF 0b111 + + +XStatus fnInitUserIO(XGpio *psGpio_out, XTmrCtr *psTmr); +void fnUserIOIsr(void *pvInst); +void fnUserIOTmrIsr(void *CallBackRef, u8 TmrCtrNumber); +void fnUpdateRgbsFromButtons(int rgb_col); + +#endif /* USERIO_H_ */ diff --git a/sw/src/Cmod-A7-35T-OOB/145_build_app.tcl b/sw/src/Cmod-A7-35T-OOB/145_build_app.tcl new file mode 100644 index 0000000..321ec0e --- /dev/null +++ b/sw/src/Cmod-A7-35T-OOB/145_build_app.tcl @@ -0,0 +1,11 @@ +# This script will build the application named after the script directory +# Workspace should be set externally + +set script [info script] +set script_dir [file normalize [file dirname $script]] + +puts "INFO: Running $script" + +set app_name [file tail $script_dir] + +app build -name $app_name \ No newline at end of file diff --git a/sw/src/Cmod-A7-35T-OOB/45_standalone_app.tcl b/sw/src/Cmod-A7-35T-OOB/45_standalone_app.tcl new file mode 100644 index 0000000..faea548 --- /dev/null +++ b/sw/src/Cmod-A7-35T-OOB/45_standalone_app.tcl @@ -0,0 +1,51 @@ +# This script will create an application named after the script directory +# based on the C "Empty Application" template and for a specific processor +# It imports all source files from the src subdirectory as LINKS. +# BUG 2020.1: linker script imported as link won't build, import by setting +# linker-script app config as a workaround. +# It also sets some C/C++ build settings +# Workspace should be set externally + +set script [info script] +set script_dir [file normalize [file dirname $script]] + +puts "INFO: Running $script" + +set app_name [file tail $script_dir] + +# Variables created by checkin.tcl +set lang "c" +set domain "domain_microblaze_0" +set platform "user_35t_wrapper" +set sysproj "Cmod-A7-35T-OOB_system" + +# Handle dependent variables +if {$lang == "c"} { + set template "Empty Application" +} elseif {$lang == "c++"} { + set template "Empty Application (C++)" +} else { + return -code error "invalid language selection in [file tail $script]; $lang should be c or c++" +} + + +# unused `app create` arguments: +# -os, -arch, and -proc are inferred from -domain? +# -hw conflicts with -platform usage +app create -name $app_name -lang $lang -template $template -domain $domain -platform $platform -sysproj $sysproj + +importsources -name $app_name -path $script_dir/src -soft-link + +# Set project settings per build configuration (handled by checkin) +app config -set -name $app_name build-config Release +app config -set -name $app_name assembler-flags {} +app config -set -name $app_name compiler-misc {-c -fmessage-length=0 -MT"$@"} +app config -set -name $app_name compiler-optimization {Optimize more (-O2)} +app config -add -name $app_name include-path $script_dir/src +app config -set -name $app_name linker-script $script_dir/src/lscript.ld +app config -set -name $app_name build-config Debug +app config -set -name $app_name assembler-flags {} +app config -set -name $app_name compiler-misc {-c -fmessage-length=0 -MT"$@"} +app config -set -name $app_name compiler-optimization {None (-O0)} +app config -add -name $app_name include-path $script_dir/src +app config -set -name $app_name linker-script $script_dir/src/lscript.ld diff --git a/sw/src/Cmod-A7-35T-OOB/src/README.txt b/sw/src/Cmod-A7-35T-OOB/src/README.txt new file mode 100644 index 0000000..c4d32ef --- /dev/null +++ b/sw/src/Cmod-A7-35T-OOB/src/README.txt @@ -0,0 +1 @@ +Empty application. Add your own sources. diff --git a/sw/src/Cmod-A7-35T-OOB/src/intc/intc.c b/sw/src/Cmod-A7-35T-OOB/src/intc/intc.c new file mode 100644 index 0000000..cb27ebd --- /dev/null +++ b/sw/src/Cmod-A7-35T-OOB/src/intc/intc.c @@ -0,0 +1,96 @@ +/****************************************************************************** + * @file iic.c + * Interrupt system initialization. + * + * @author Elod Gyorgy + * + * @date 2015-Jan-3 + * + * @copyright + * (c) 2015 Copyright Digilent Incorporated + * All Rights Reserved + * + * This program is free software; distributed under the terms of BSD 3-clause + * license ("Revised BSD License", "New BSD License", or "Modified BSD License") + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name(s) of the above-listed copyright holder(s) nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * @desciption + * Contains interrupt controller initialization function. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who          Date     Changes
+ * ----- ------------ ----------- -----------------------------------------------
+ * 1.00  Elod Gyorgy  2015-Jan-3 First release
+ *
+ * 
+ * + *****************************************************************************/ + +#include "intc.h" +#include "xparameters.h" + +#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID + +XStatus fnInitInterruptController(XIntc *psIntc) +{ + // Init driver instance + RETURN_ON_FAILURE(XIntc_Initialize(psIntc, INTC_DEVICE_ID)); + + // Start interrupt controller + RETURN_ON_FAILURE(XIntc_Start(psIntc, XIN_REAL_MODE)); + + Xil_ExceptionInit(); + // Register the interrupt controller handler with the exception table. + // This is in fact the ISR dispatch routine, which calls our ISRs + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, + (Xil_ExceptionHandler)XIntc_InterruptHandler, + psIntc); + Xil_ExceptionEnable(); + + return XST_SUCCESS; +} + +/* + * This function enables interrupts and connects interrupt service routines declared in + * an interrupt vector table + */ +void fnEnableInterrupts(XIntc *psIntc, const ivt_t *prgsIvt, unsigned int csIVectors) +{ + unsigned int isIVector; + + Xil_AssertVoid(psIntc != NULL); + Xil_AssertVoid(psIntc->IsReady == XIL_COMPONENT_IS_READY); + + /* Hook up interrupt service routines from IVT */ + for (isIVector = 0; isIVector < csIVectors; isIVector++) + { + XIntc_Connect(psIntc, prgsIvt[isIVector].id, prgsIvt[isIVector].handler, prgsIvt[isIVector].pvCallbackRef); + + /* Enable the interrupt vector at the interrupt controller */ + XIntc_Enable(psIntc, prgsIvt[isIVector].id); + } +} diff --git a/sw/src/Cmod-A7-35T-OOB/src/intc/intc.h b/sw/src/Cmod-A7-35T-OOB/src/intc/intc.h new file mode 100644 index 0000000..1ab5b7c --- /dev/null +++ b/sw/src/Cmod-A7-35T-OOB/src/intc/intc.h @@ -0,0 +1,75 @@ +/****************************************************************************** + * @file intc.h + * Interrupt system initialization. + * + * @author Elod Gyorgy + * + * @date 2015-Jan-3 + * + * @copyright + * (c) 2015 Copyright Digilent Incorporated + * All Rights Reserved + * + * This program is free software; distributed under the terms of BSD 3-clause + * license ("Revised BSD License", "New BSD License", or "Modified BSD License") + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name(s) of the above-listed copyright holder(s) nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * @desciption + * Contains interrupt controller initialization function. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who          Date     Changes
+ * ----- ------------ ----------- -----------------------------------------------
+ * 1.00  Elod Gyorgy  2015-Jan-3 First release
+ *
+ * 
+ * + *****************************************************************************/ + +#ifndef INTC_H_ +#define INTC_H_ + +#include "xstatus.h" +#include "xintc.h" + + +#define RETURN_ON_FAILURE(x) if ((x) != XST_SUCCESS) return XST_FAILURE; + +/* + * Structure for interrupt id, handler and callback reference + */ +typedef struct { + u8 id; + XInterruptHandler handler; + void *pvCallbackRef; +} ivt_t; + +XStatus fnInitInterruptController(XIntc *psIntc); +void fnEnableInterrupts(XIntc *psIntc, const ivt_t *prgsIvt, unsigned int csIVectors); + + +#endif /* INTC_H_ */ diff --git a/sw/src/Cmod-A7-35T-OOB/src/lscript.ld b/sw/src/Cmod-A7-35T-OOB/src/lscript.ld new file mode 100644 index 0000000..619653c --- /dev/null +++ b/sw/src/Cmod-A7-35T-OOB/src/lscript.ld @@ -0,0 +1,213 @@ +/*******************************************************************/ +/* */ +/* This file is automatically generated by linker script generator.*/ +/* */ +/* Version: */ +/* */ +/* Copyright (c) 2010 Xilinx, Inc. All rights reserved. */ +/* */ +/* Description : MicroBlaze Linker Script */ +/* */ +/*******************************************************************/ + +_STACK_SIZE = DEFINED(_STACK_SIZE) ? _STACK_SIZE : 0x400; +_HEAP_SIZE = DEFINED(_HEAP_SIZE) ? _HEAP_SIZE : 0x0; + +/* Define Memories in the system */ + +MEMORY +{ + microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr : ORIGIN = 0x50, LENGTH = 0x7FB0 + axi_emc_0_S_AXI_MEM0_BASEADDR : ORIGIN = 0x60000000, LENGTH = 0x2000000 +} + +/* Specify the default entry point to the program */ + +ENTRY(_start) + +/* Define the sections, and where they are mapped in memory */ + +SECTIONS +{ +.vectors.reset 0x0 : { + KEEP (*(.vectors.reset)) +} + +.vectors.sw_exception 0x8 : { + KEEP (*(.vectors.sw_exception)) +} + +.vectors.interrupt 0x10 : { + KEEP (*(.vectors.interrupt)) +} + +.vectors.hw_exception 0x20 : { + KEEP (*(.vectors.hw_exception)) +} + +.text : { + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +.init : { + KEEP (*(.init)) +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +.fini : { + KEEP (*(.fini)) +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +.ctors : { + __CTOR_LIST__ = .; + ___CTORS_LIST___ = .; + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE(*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + __CTOR_END__ = .; + ___CTORS_END___ = .; +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +.dtors : { + __DTOR_LIST__ = .; + ___DTORS_LIST___ = .; + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE(*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + PROVIDE(__DTOR_END__ = .); + PROVIDE(___DTORS_END___ = .); +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +.rodata : { + __rodata_start = .; + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + __rodata_end = .; +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +.sdata2 : { + . = ALIGN(8); + __sdata2_start = .; + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + . = ALIGN(8); + __sdata2_end = .; +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +.sbss2 : { + __sbss2_start = .; + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + __sbss2_end = .; +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +.data : { + . = ALIGN(4); + __data_start = .; + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + __data_end = .; +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +.got : { + *(.got) +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +.got1 : { + *(.got1) +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +.got2 : { + *(.got2) +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +.eh_frame : { + *(.eh_frame) +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +.jcr : { + *(.jcr) +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +.gcc_except_table : { + *(.gcc_except_table) +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +.sdata : { + . = ALIGN(8); + __sdata_start = .; + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + __sdata_end = .; +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +.sbss (NOLOAD) : { + . = ALIGN(4); + __sbss_start = .; + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + . = ALIGN(8); + __sbss_end = .; +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +.tdata : { + __tdata_start = .; + *(.tdata) + *(.tdata.*) + *(.gnu.linkonce.td.*) + __tdata_end = .; +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +.tbss : { + __tbss_start = .; + *(.tbss) + *(.tbss.*) + *(.gnu.linkonce.tb.*) + __tbss_end = .; +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +.bss (NOLOAD) : { + . = ALIGN(4); + __bss_start = .; + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +_SDA_BASE_ = __sdata_start + ((__sbss_end - __sdata_start) / 2 ); + +_SDA2_BASE_ = __sdata2_start + ((__sbss2_end - __sdata2_start) / 2 ); + +/* Generate Stack and Heap definitions */ + +.heap (NOLOAD) : { + . = ALIGN(8); + _heap = .; + _heap_start = .; + . += _HEAP_SIZE; + _heap_end = .; +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +.stack (NOLOAD) : { + _stack_end = .; + . += _STACK_SIZE; + . = ALIGN(8); + _stack = .; + __stack = _stack; +} > microblaze_0_local_memory_ilmb_bram_if_cntlr_microblaze_0_local_memory_dlmb_bram_if_cntlr + +_end = .; +} + diff --git a/sw/src/Cmod-A7-35T-OOB/src/memory_config.h b/sw/src/Cmod-A7-35T-OOB/src/memory_config.h new file mode 100644 index 0000000..14c411d --- /dev/null +++ b/sw/src/Cmod-A7-35T-OOB/src/memory_config.h @@ -0,0 +1,47 @@ +/****************************************************************************** +* +* Copyright (C) 2008 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#ifndef __MEMORY_CONFIG_H_ +#define __MEMORY_CONFIG_H_ + +struct memory_range_s { + char *name; + char *ip; + unsigned base; + unsigned size; +}; + +/* generated memory ranges defined in memory_ranges_g.c */ +extern struct memory_range_s memory_ranges[]; +extern int n_memory_ranges; + +#endif diff --git a/sw/src/Cmod-A7-35T-OOB/src/memory_config_g.c b/sw/src/Cmod-A7-35T-OOB/src/memory_config_g.c new file mode 100644 index 0000000..a142f31 --- /dev/null +++ b/sw/src/Cmod-A7-35T-OOB/src/memory_config_g.c @@ -0,0 +1,10 @@ +/* This file is automatically generated based on your hardware design. */ +#include "memory_config.h" +#include "xparameters.h" + +struct memory_range_s memory_ranges[] = { + /* microblaze_0_local_memory_dlmb_bram_if_cntlr memory will not be tested since application resides in the same memory */ + {"Cellular Ram", "emc", XPAR_EMC_0_S_AXI_MEM0_BASEADDR, 524287} +}; + +int n_memory_ranges = 1; diff --git a/sw/src/Cmod-A7-35T-OOB/src/memorytest.c b/sw/src/Cmod-A7-35T-OOB/src/memorytest.c new file mode 100644 index 0000000..a337fe0 --- /dev/null +++ b/sw/src/Cmod-A7-35T-OOB/src/memorytest.c @@ -0,0 +1,209 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#include +#include "xparameters.h" +#include "xil_types.h" +#include "xstatus.h" +#include "xil_testmem.h" +#include "xgpio.h" +#include "microblaze_sleep.h" + +#include "platform.h" +#include "memory_config.h" + + +#include "intc/intc.h" +#include "userio/userio.h" + +static XIntc sIntc; + +/* + * memory_test.c: Test memory ranges present in the Hardware Design. + * + * This application runs with D-Caches disabled. As a result cacheline requests + * will not be generated. + * + * For MicroBlaze/PowerPC, the BSP doesn't enable caches and this application + * enables only I-Caches. For ARM, the BSP enables caches by default, so this + * application disables D-Caches before running memory tests. + */ + +/************************** Variable Definitions *****************************/ + +/* + * The following are declared globally so they are zeroed and so they are + * easily accessible from a debugger + */ + +XGpio Gpio1; /* The Instance of the GPIO Driver for Leds and buttons */ +#define LED_CHANNEL 1 +#define BTN_CHANNEL 2 +#define LED_MASK 0x03 +#define BTN_MASK 0x01 + +XGpio Gpio2; /* The Instance of the GPIO Driver for the RGB Leds */ +#define RGB_MASK 0x07 + +void putnum(unsigned int num); +//void xil_printf(char *ptr); + + + +static XTmrCtr sTmr; + +// interrupt vector table +const ivt_t ivt[] = { + // User I/O + {XPAR_AXI_INTC_0_AXI_TIMER_0_INTERRUPT_INTR, (XInterruptHandler)XTmrCtr_InterruptHandler, &sTmr} +}; + + +void test_memory_range(struct memory_range_s *range) { + XStatus status; + + /* This application uses xil_printf statements instead of xil_xil_printff/xil_printff + * to reduce the text size. + * + * The default linker script generated for this application does not have + * heap memory allocated. This implies that this program cannot use any + * routines that allocate memory on heap (xil_printff is one such function). + * If you'd like to add such functions, then please generate a linker script + * that does allocate sufficient heap memory. + */ + + xil_printf("Testing memory region: "); xil_printf(range->name); xil_printf("\n\r"); + xil_printf(" Memory Controller: "); xil_printf(range->ip); xil_printf("\n\r"); + xil_printf(" Base Address: 0x"); putnum(range->base); xil_printf("\n\r"); + xil_printf(" Size: 0x"); putnum(range->size); xil_printf (" bytes \n\r"); + + status = Xil_TestMem32((u32*)range->base, ((range->size)/32), 0xAAAA5555, XIL_TESTMEM_ALLMEMTESTS); + xil_printf(" 32-bit test: "); xil_printf(status == XST_SUCCESS? "PASSED!":"FAILED!"); xil_printf("\n\r"); + + status = Xil_TestMem16((u16*)range->base, ((range->size)/16), 0xAA55, XIL_TESTMEM_ALLMEMTESTS); + xil_printf(" 16-bit test: "); xil_printf(status == XST_SUCCESS? "PASSED!":"FAILED!"); xil_printf("\n\r"); + + status = Xil_TestMem8((u8*)range->base, ((range->size)/8), 0xA5, XIL_TESTMEM_ALLMEMTESTS); + xil_printf(" 8-bit test: "); xil_printf(status == XST_SUCCESS? "PASSED!":"FAILED!"); xil_printf("\n\r"); + +} + +int main() +{ + int i; + int Status = 0; + int leds = 0; + int rgb_col = 0; + int button = 0; + int last_button = 0; + + init_platform(); + + xil_printf("--Starting Memory Test Application--\n\r"); + xil_printf("NOTE: This application runs with D-Cache disabled."); + xil_printf("As a result, cacheline requests will not be generated\n\r"); + + for (i = 0; i < n_memory_ranges; i++) { + test_memory_range(&memory_ranges[i]); + } + + xil_printf("--Memory Test Application Complete--\n\r"); + + + //once past memory testing enter GPIO loop + Status = XGpio_Initialize(&Gpio1, XPAR_AXI_GPIO_0_DEVICE_ID); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + Status = XGpio_Initialize(&Gpio2, XPAR_AXI_GPIO_1_DEVICE_ID); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + //set leds to outputs and the button to an input + XGpio_SetDataDirection(&Gpio1, LED_CHANNEL, ~LED_MASK); + XGpio_SetDataDirection(&Gpio1, BTN_CHANNEL, BTN_MASK); + XGpio_SetDataDirection(&Gpio2, RGB_CHANNEL, ~RGB_MASK); + + // Initialize the interrupt controller + Status = fnInitInterruptController(&sIntc); + if(Status != XST_SUCCESS) { + xil_printf("\r\nError initializing interrupts"); + return XST_FAILURE; + } + + // Initializing User I/O GPIO driver + Status = fnInitUserIO(&Gpio2, &sTmr); + if(Status != XST_SUCCESS) { + xil_printf("\r\nError initializing User I/O"); + return XST_FAILURE; + } + + // Enable all interrupts in our interrupt vector table + // Make sure all driver instances using this IVT are initialized first + fnEnableInterrupts(&sIntc, &ivt[0], sizeof(ivt)/sizeof(ivt[0])); + + + while(1){ + //read button + button = XGpio_DiscreteRead(&Gpio1, BTN_CHANNEL); + //if it is 1 and the last press was zero then assign new leds + if(button == BTN_MASK && button != last_button){ + + last_button = button; + rgb_col ++; + rgb_col = rgb_col % 8; + leds ++; + leds = leds % 4; + switch(rgb_col){ //colors RGB + case 1: fnUpdateRgbsFromButtons(3);break; //red 0b011 + case 2: fnUpdateRgbsFromButtons(5);break; //green 0b101 + case 3: fnUpdateRgbsFromButtons(6);break; //blue 0b110 + case 4: fnUpdateRgbsFromButtons(4);break; //cyan 0b100 + case 5: fnUpdateRgbsFromButtons(2);break; //magenta 0b010 + case 6: fnUpdateRgbsFromButtons(1);break; //yellow 0b001 + case 7: fnUpdateRgbsFromButtons(0);break; //white 0b000 + case 0: fnUpdateRgbsFromButtons(7);break; //off 0b111 + } + XGpio_DiscreteWrite(&Gpio1, LED_CHANNEL, leds & LED_MASK); + xil_printf("\r\nButton Pressed"); + } + else + last_button = button; + + + } + + cleanup_platform(); + return 0; +} diff --git a/sw/src/Cmod-A7-35T-OOB/src/platform.c b/sw/src/Cmod-A7-35T-OOB/src/platform.c new file mode 100644 index 0000000..08539f3 --- /dev/null +++ b/sw/src/Cmod-A7-35T-OOB/src/platform.c @@ -0,0 +1,94 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#include "xparameters.h" +#include "xil_cache.h" + +#include "platform_config.h" + +#ifdef STDOUT_IS_16550 +#include "xuartns550_l.h" +#endif + +void +enable_caches() +{ +#ifdef __PPC__ + Xil_ICacheEnableRegion(XPAR_CACHEABLE_REGION_MASK); + // Do not enable caches for memory tests, this has pros and cons + // Pros - If caches are enabled, under certain configurations, there will be very few + // transactions to external memory + // Con - This might not generate a burst cacheline request + // Xil_DCacheEnableRegion(CACHEABLE_REGION_MASK); +#elif __MICROBLAZE__ +#ifdef XPAR_MICROBLAZE_USE_ICACHE + Xil_ICacheEnable(); +#endif +#ifdef XPAR_MICROBLAZE_USE_DCACHE + // See reason above for not enabling D Cache + // Xil_DCacheEnable(); +#endif +#elif __arm__ + // For ARM, BSP enables caches by default. +#endif +} + +void +disable_caches() +{ + Xil_DCacheDisable(); + Xil_ICacheDisable(); +} + +void +init_platform() +{ + enable_caches(); + +#ifdef __arm__ + // For ARM, BSP enables caches by default. Disable them here. + // See reason above for disabling D Cache + Xil_DCacheDisable(); +#endif + + /* if we have a uart 16550, then that needs to be initialized */ +#ifdef STDOUT_IS_16550 + XUartNs550_SetBaud(STDOUT_BASEADDR, XPAR_XUARTNS550_CLOCK_HZ, 9600); + XUartNs550_SetLineControlReg(STDOUT_BASEADDR, XUN_LCR_8_DATA_BITS); +#endif +} + +void +cleanup_platform() +{ + disable_caches(); +} diff --git a/sw/src/Cmod-A7-35T-OOB/src/platform.h b/sw/src/Cmod-A7-35T-OOB/src/platform.h new file mode 100644 index 0000000..e273e37 --- /dev/null +++ b/sw/src/Cmod-A7-35T-OOB/src/platform.h @@ -0,0 +1,41 @@ +/****************************************************************************** +* +* Copyright (C) 2008 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#ifndef __PLATFORM_H_ +#define __PLATFORM_H_ + +#include "platform_config.h" + +void init_platform(); +void cleanup_platform(); + +#endif diff --git a/sw/src/Cmod-A7-35T-OOB/src/platform_config.h b/sw/src/Cmod-A7-35T-OOB/src/platform_config.h new file mode 100644 index 0000000..70b9b1a --- /dev/null +++ b/sw/src/Cmod-A7-35T-OOB/src/platform_config.h @@ -0,0 +1,4 @@ +#ifndef __PLATFORM_CONFIG_H_ +#define __PLATFORM_CONFIG_H_ + +#endif diff --git a/sw/src/Cmod-A7-35T-OOB/src/userio/userio.c b/sw/src/Cmod-A7-35T-OOB/src/userio/userio.c new file mode 100644 index 0000000..b949da3 --- /dev/null +++ b/sw/src/Cmod-A7-35T-OOB/src/userio/userio.c @@ -0,0 +1,188 @@ +/****************************************************************************** + * @file userio.c + * + * @authors Elod Gyorgy + * + * @date 2015-Jan-03 + * + * @copyright + * (c) 2015 Copyright Digilent Incorporated + * All Rights Reserved + * + * This program is free software; distributed under the terms of BSD 3-clause + * license ("Revised BSD License", "New BSD License", or "Modified BSD License") + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name(s) of the above-listed copyright holder(s) nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * @desciption + * + * @note + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who          Date        Changes
+ * ----- ------------ ----------- --------------------------------------------
+ * 1.00  Elod Gyorgy  2015-Jan-03 First release
+ *
+ * 
+ * + *****************************************************************************/ + +#include +#include "xparameters.h" +#include "userio.h" + +/* + * The timer is used to generate a PWM signal for the RGB LEDs. + * the first timer is used for the PWM Period, the second for setting the PWM Pulse + */ +#define TMR_NUM_PERIOD 0 +#define TMR_NUM_PULSE 1 + +/* + * To achieve a 1 KHz PWM frequency, the Timer should count to 100,000 ticks, + * assuming the clock is 100 MHz (100,000,000/1,000/2). + */ +#define TMR_PERIOD_CNT 2000 + +/* + * This is the number of ticks to keep the pulse high. The duty cycle is + * TMR_PULSE_CNT/TMR_PERIOD_CNT + */ +#define TMR_PULSE_CNT 150 + +extern unsigned char u8UserIO; + +static u32 rgb_color; +const u32 rgb_colorarray[] = { + RGB_RED, + RGB_GREEN, + RGB_BLUE, + RGB_MAGENTA, + RGB_CYAN, + RGB_YELLOW, + RGB_WHITE, + RGB_OFF +}; + +//Yea, these globals are stupid, but I needed access to the input and output XGpios from the ISR, +//and this is simpler than defining a custom struct that contains both. --Sam +static XGpio *RGB_global; + +void fnUpdateLedsFromSwitches(); +void fnUpdateRgbsFromButtons(); + +XStatus fnInitUserIO(XGpio *Gpio2, XTmrCtr *psTmr) +{ + /* Initialize the GPIO driver. If an error occurs then exit */ + + /* + * Perform a self-test on the GPIO. This is a minimal test and only + * verifies that there is not any bus error when reading the data + * register + */ + + /* + * Setup direction register so the switches and buttons are inputs and the LED is + * an output of the GPIO + */ + + + RGB_global = Gpio2; +// +// fnUpdateLedsFromSwitches(); + rgb_color = RGB_OFF; + XGpio_DiscreteWrite(Gpio2, RGB_CHANNEL, 0); + + /* + * Enable the GPIO channel interrupts so that push button can be + * detected and enable interrupts for the GPIO device + */ + + /* + * Initialize timer for RGB LED PWMing + */ + RETURN_ON_FAILURE(XTmrCtr_Initialize(psTmr, XPAR_AXI_TIMER_0_DEVICE_ID)); + RETURN_ON_FAILURE(XTmrCtr_SelfTest(psTmr, TMR_NUM_PERIOD)); + RETURN_ON_FAILURE(XTmrCtr_SelfTest(psTmr, TMR_NUM_PULSE)); + + /* + * Setup the handler for the timer counter + */ + XTmrCtr_SetHandler(psTmr, fnUserIOTmrIsr, psTmr); + + /* + * Enable the interrupt of the timer counter so interrupts will occur + * and use auto reload mode such that the timer counter will reload + * itself automatically and continue repeatedly, without this option + * it would expire once only. Also count down + */ + XTmrCtr_SetOptions(psTmr, TMR_NUM_PERIOD, + XTC_INT_MODE_OPTION | XTC_AUTO_RELOAD_OPTION | XTC_DOWN_COUNT_OPTION); + /* + * The Pulse timer also uses the interrupt and counts down + */ + XTmrCtr_SetOptions(psTmr, TMR_NUM_PULSE, + XTC_INT_MODE_OPTION | XTC_DOWN_COUNT_OPTION); + + + XTmrCtr_SetResetValue(psTmr, TMR_NUM_PERIOD, TMR_PERIOD_CNT); + XTmrCtr_SetResetValue(psTmr, TMR_NUM_PULSE, TMR_PULSE_CNT); + + /* + * Start the timer counter. Interrupts will begin being triggered (at the + * timer layer). Don't start the pulse timer until in the ISR + */ + XTmrCtr_Start(psTmr, TMR_NUM_PERIOD); + + return XST_SUCCESS; +} + +void fnUpdateRgbsFromButtons(int rgb_col) +{ + rgb_color = rgb_col; +} + +/* + * Timer interrupt service routine + */ +void fnUserIOTmrIsr(void *CallBackRef, u8 TmrCtrNumber) +{ + XTmrCtr *psTmr = (XTmrCtr *)CallBackRef; + + + if (TmrCtrNumber == TMR_NUM_PERIOD) + { + + XTmrCtr_Start(psTmr, TMR_NUM_PULSE); + + XGpio_DiscreteWrite(RGB_global, RGB_CHANNEL, rgb_color); + } + else + { + XGpio_DiscreteWrite(RGB_global, RGB_CHANNEL, 7); + } +} + diff --git a/sw/src/Cmod-A7-35T-OOB/src/userio/userio.h b/sw/src/Cmod-A7-35T-OOB/src/userio/userio.h new file mode 100644 index 0000000..dfd3f5a --- /dev/null +++ b/sw/src/Cmod-A7-35T-OOB/src/userio/userio.h @@ -0,0 +1,93 @@ +/****************************************************************************** + * @file userio.h + * + * @authors Elod Gyorgy + * + * @date 2015-Jan-03 + * + * @copyright + * (c) 2015 Copyright Digilent Incorporated + * All Rights Reserved + * + * This program is free software; distributed under the terms of BSD 3-clause + * license ("Revised BSD License", "New BSD License", or "Modified BSD License") + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name(s) of the above-listed copyright holder(s) nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * @desciption + * + * @note + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who          Date        Changes
+ * ----- ------------ ----------- --------------------------------------------
+ * 1.00  Elod Gyorgy  2015-Jan-03 First release
+ *
+ * 
+ * + *****************************************************************************/ + +#ifndef USERIO_H_ +#define USERIO_H_ + +#include "xstatus.h" +#include "xgpio.h" +#include "xtmrctr.h" + +#define RGB_CHANNEL 1 /* Channel 2 of the output GPIO Device */ +#define SW_INTERRUPT XGPIO_IR_CH1_MASK /* Channel 1 Interrupt Mask */ +#define BTN_INTERRUPT XGPIO_IR_CH2_MASK /* Channel 2 Interrupt Mask */ + +//#define BTNU_MASK 0x0100 +//#define BTNR_MASK 0x0200 +//#define BTND_MASK 0x0400 +//#define BTNL_MASK 0x0800 +//#define BTNC_MASK 0x1000 +#define SWS_MASK 0x000F +#define BTNS_MASK 0x001F +#define RESET_MASK 0x0010 + +#define LEDS_MASK 0x00F +#define RGBS_MASK 0xFFF + +#define RETURN_ON_FAILURE(x) if ((x) != XST_SUCCESS) return XST_FAILURE; + +#define RGB_WHITE 0b000 +#define RGB_RED 0b011 +#define RGB_GREEN 0b101 +#define RGB_YELLOW 0b101 +#define RGB_CYAN 0b101 +#define RGB_MAGENTA 0b101 +#define RGB_BLUE 0b110 +#define RGB_OFF 0b111 + + +XStatus fnInitUserIO(XGpio *psGpio_out, XTmrCtr *psTmr); +void fnUserIOIsr(void *pvInst); +void fnUserIOTmrIsr(void *CallBackRef, u8 TmrCtrNumber); +void fnUpdateRgbsFromButtons(int rgb_col); + +#endif /* USERIO_H_ */ diff --git a/sw/src/README.md b/sw/src/README.md new file mode 100644 index 0000000..6a128b8 --- /dev/null +++ b/sw/src/README.md @@ -0,0 +1,61 @@ +# digilent-vitis-scripts +This repository contains a set of scripts for managing Vitis workspaces with git. + +---- +## Quick Checkout Guide + +When cloning this repository, use the command `git clone --recursive ` to pick up any submodules this repository may use to bring in additional source files. Alternatively initialize and update the repository's submodules after cloning (`git submodule update --init` within the repo directory). + +Some Digilent Github repositories also require that you check out a specific demo branch. Whenever checking out a demo branch, submodules should be reupdated and reinitialized (`git submodule update --init`, as above). + +When launching Vitis, whether through Vivado's *Tools* menu, or on its own, the Vitis workspace should be set to the repository's sw/ws folder. + +The scripts present in this repository can be run through the use of the Xilinx Software Command-Line Tool (XSCT), which is built into Vitis. This tool can be opened within the Vitis GUI through the *Xilinx > XSCT Console* option in the menu bar at the top of the window. Upon launch, XSCT's current working directory is set to the Vitis install directory. To recreate the workspace, enter the following command into the XSCT Console: + +`source [getws]/../src/checkout.tcl` + +This process will populate the workspace with projects containing sources from the parent repository's src folder, configure those projects, and fully build them. This may take several minutes to fully complete. When the script is finished running, the `xsct%` prompt wil reappear in the tan XSCT Process pane. From this point, the demo can be programmed onto a board, sources can be viewed, and modified, as desired. + +**Note:** *The current working directory is irrelevant to the functionality of the scripts in this submodule.* + +---- +## Quick Checkin Guide + +**Important:** *The checkin.tcl script should generally only be used for the first time checking a project into version control. For further commits, new files should be manually copied into the repository's src directory. Application source files (and linker scripts) are soft-linked into the workspace upon checkout, so existing files do not need to be manually copied back. Modifications to project settings require that the corresponding scripts in the repository's src directory be edited.* + +This section assumes that you have already created a Vitis workspace containing one or more application projects. Some additional work may be required after the checkin script is completed, and it is important that you try the checkout process afterwards to ensure that all important settings are properly included. + +The checkin script has only been tested with standalone application projects at time of writing. + +To add this repository to a parent repository as a submodule, first open a terminal with access to git. If your parent repository does not yet have a `sw` subdirectory (or submodule), create one and cd into it. Adding the `scripts` path argument to the command is recommended in order to keep file paths short. + +`git submodule add https://github.com/Digilent/digilent-vitis-scripts scripts` + +Open your workspace in Vitis. Open the XSCT Console from within the Vitis GUI by selecting the *Xilinx > XSCT Console* option in the menu bar at the top of the window. To copy all relevant (local only!) source files into the parent repository's src directory and create the scripts used by checkout.tcl, run the following command: + +`source /checkin.tcl` + +This script will create a src directory in the same folder as the scripts submodule, and populate it as below: + +* checkout.tcl script and README file +* One folder per application project, containing the following: + * A src directory, containing the application project's local sources (from its src folder) and linker script. + * A #_standalone_app.tcl script, containing the XSCT commands required to recreate and configure the project. + * A #_build_app.tcl script, containing the XSCT commands required to build the project. +* One folder per (non-automatically generated) domain, containing the following: + * A #_standalone_bsp.tcl script containing the XSCT commands to recreate and configure the domain. +* One folder per hardware platform, containing the following: + * A #_hw_pf_xsa.tcl script, containing the XSCT commands required to recreate and configure the platform, using only the XSA as input. + * The XSA file describing the hardware specification that the software targets, exported from Vivado. + +Additionally, a gitignore file is created in the parent repository's sw directory. + +Note that the name of each folder is used in checkout to determine the name of the app/platform/domain it is used to create. + +The numeric prefixes for XSCT scripts are used to determine the order in which they are sourced during checkout (lowest to highest). Recommended: 0-9 for hardware platform, 20-29 for bsp, 40-49 for app creation. Build scripts are recommended to use > 100. + +As mentioned above, you MUST test the checkout process and check the generated scripts to ensure that all sources, project settings, and build configuration settings are correctly applied to the projects when someone else checks them out. + +The checkin script is *not* perfect, and manual intervention is likely to be required after the script is run. Edit the automatically generated scripts as needed, and double check your source files. + +---- diff --git a/sw/src/checkout.tcl b/sw/src/checkout.tcl new file mode 100644 index 0000000..16fe7ec --- /dev/null +++ b/sw/src/checkout.tcl @@ -0,0 +1,102 @@ +# Run this script to create the Vitis workspace in the /ws/ sub-directory +# If ::create_path global variable is set, the project is created under that path instead of ws/ + +set script [info script] +set script_dir [file normalize [file dirname $script]] + +puts "INFO: Running $script." + +if {[info exists ::create_path]} { + set dest_dir $::create_path +} else { + set dest_dir [file normalize $script_dir/../ws] +} + +set src_dir [file normalize $script_dir/../src] + +puts "INFO: Targeting $dest_dir for workspace creation." + +# Check workspace for existing sub-dirs +if { [llength [glob -nocomplain -types d $dest_dir/*]] != 0 } { + # If the workspace is already set to the destination directory + if { [file normalize [getws]] == [file normalize $dest_dir] } { + # Check if the workspace is empty, which it will be if Vitis is launched in an empty directory + if { [catch {app list} ] == 0 || [catch {platform list} ] == 0 || [catch {domain list} ] == 0 || [catch {library list} ] == 0 } { + puts "WARNING: workspace is not empty. Close Vitis or XSCT to relinquish control and run the cleanup scripts. Re-run create_workspace.tcl afterwards." + flush stdout; + return -code error "Workspace already exists and needs to be closed first" + } + } else { + puts -nonewline "WARNING: workspace is not empty. Continuing might cause naming conflicts and workspace creation to fail. Recommend running the cleanup scripts before continuing. Continue? (y/n):" + while 1 { + flush stdout; + if {[gets stdin input] < 0 && [eof stdin]} { + return -code error "end of file detected" + } + if { [regexp -nocase -line -- {^(y|n|yes|no)$} $input] } { + break + } + puts -nonewline "Continue? (y/n):" + } + if { [string equal -nocase -length 1 $input "n"] } { + return -code ok + } + } +} + +# Change directory +set popd [pwd] +cd $dest_dir + +catch { + setws -switch $dest_dir + + # Get all *.tcl files in src_dir recursively and sort them by integer prefix + proc deep_traverse {base glob} { + set files [list] + + foreach d [glob -nocomplain -types d -directory $base *] { + lappend files {*}[deep_traverse $d $glob] + } + foreach f [glob -nocomplain -types f -directory $base -- $glob] { + lappend files [file normalize $f] + } + return $files + } + + proc sort_by_fileprefix {file1 file2} { + set i1 [scan [file tail $file1] "%d"] + set i2 [scan [file tail $file2] "%d"] + + return [expr $i1 > $i2] + } + + set scripts [deep_traverse $src_dir "*.tcl"] + # Self should be there + set selfs [lsearch -all $scripts [file normalize $script]] + if { [llength $selfs] eq 0 } { + return -code error "ERROR: Self not found while deep searching $src_dir" + } + # Remove all instances of self to avoid recursive call below + foreach idx $selfs { + set scripts [lreplace $scripts $idx $idx] + } + # Order by integer prefix + set ordered_scripts [lsort -command sort_by_fileprefix $scripts] + + puts "INFO: Found the following subscripts:" + foreach s $ordered_scripts { + puts $s + } + + # Source each subscript in order + foreach s $ordered_scripts { + source $s + } + +} result options + +puts "Changing back working dir to: $popd" +cd $popd + +return -options $options $result diff --git a/sw/src/domain_microblaze_0/25_standalone_bsp.tcl b/sw/src/domain_microblaze_0/25_standalone_bsp.tcl new file mode 100644 index 0000000..d32c4e0 --- /dev/null +++ b/sw/src/domain_microblaze_0/25_standalone_bsp.tcl @@ -0,0 +1,35 @@ +# This script will create a standalone domain for a processor and its architecture +# Workspace should be set externally + +set script [info script] +set script_dir [file normalize [file dirname $script]] + +puts "INFO: Running $script" + +set domain_name [file tail $script_dir] + +# Modify these for custom domain/BSP settings +set arch "32-bit" +set os "standalone" +set proc "microblaze_0" + +domain create -name $domain_name -proc $proc -arch $arch -os $os + +# Customize BSP, this replaces *.mss file +bsp config clocking "false" +bsp config enable_sw_intrusive_profiling "false" +bsp config hypervisor_guest "false" +bsp config lockstep_mode_debug "false" +bsp config microblaze_exceptions "false" +bsp config predecode_fpu_exceptions "false" +bsp config profile_timer "none" +bsp config sleep_timer "none" +bsp config stdin "axi_uartlite_0" +bsp config stdout "axi_uartlite_0" +bsp config ttc_select_cntr "2" +bsp config zynqmp_fsbl_bsp "false" +bsp config archiver "mb-ar" +bsp config assembler "mb-as" +bsp config compiler "mb-gcc" +bsp config compiler_flags "-O2 -c" +bsp config extra_compiler_flags "-g -ffunction-sections -fdata-sections -Wall -Wextra" diff --git a/sw/src/user_35t_wrapper/5_hw_pf_xsa.tcl b/sw/src/user_35t_wrapper/5_hw_pf_xsa.tcl new file mode 100644 index 0000000..44839d6 --- /dev/null +++ b/sw/src/user_35t_wrapper/5_hw_pf_xsa.tcl @@ -0,0 +1,20 @@ +# This script will take the first *.xsa file near it and create a new platform based on it +# Workspace should be set externally + +set script [info script] +set script_dir [file normalize [file dirname $script]] + +puts "INFO: Running $script" + +set hw_src [lindex [glob -nocomplain $script_dir/*.xsa] 0] + +puts "INFO: Found $hw_src" + +set hw_name [file tail $script_dir] + +platform create -name "$hw_name" -hw "$hw_src" + +platform config -extra-compiler-flags fsbl "" +platform config -extra-linker-flags fsbl "" +platform config -extra-compiler-flags pmufw "" +platform config -extra-linker-flags pmufw "" diff --git a/sw/src/user_35t_wrapper/user_35t_wrapper.xsa b/sw/src/user_35t_wrapper/user_35t_wrapper.xsa new file mode 100644 index 0000000000000000000000000000000000000000..d748a544e510958940c9c327df0ff30379417824 GIT binary patch literal 239384 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

A1ibap~eXgz|r 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 gLrQC3TC~)ZEoLZ{k4Y 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 JoC`%A{2z;4!(;#e literal 0 HcmV?d00001 diff --git a/sw/ws/cleanup.cmd b/sw/ws/cleanup.cmd new file mode 100644 index 0000000..a2edfad --- /dev/null +++ b/sw/ws/cleanup.cmd @@ -0,0 +1,24 @@ +@echo off +rem save current working directory +pushd %~dp0 + +rem delete all files from subfolders +for /d /r %%i in (*) do del /f /q %%i\* +rem delete all subfolders +for /d %%i in (*) do rd /S /Q %%i + +rem unmark read only from all files +attrib -R .\* /S + +rem mark read only those we wish to keep +attrib +R .\cleanup.sh +attrib +R .\cleanup.cmd + +rem delete all non read-only +del /Q /A:-R .\* + +rem unmark read-only +attrib -R .\* + +rem restore original working directory +popd \ No newline at end of file diff --git a/sw/ws/cleanup.sh b/sw/ws/cleanup.sh new file mode 100644 index 0000000..df1dd41 --- /dev/null +++ b/sw/ws/cleanup.sh @@ -0,0 +1,14 @@ +# This script is useful for cleaning up the 'project' +# directory of a Digilent Vivado-project git repository +### +# Run the following command to change permissions of +# this 'cleanup' file if needed: +# chmod u+x cleanup.sh +### +script_dir=$(dirname ${BASH_SOURCE[0]}) +# Remove directories/subdirectories +find $script_dir -mindepth 1 -type d -exec rm -rf {} + +# Remove any other files than: +find $script_dir -type f ! -name 'cleanup.sh' \ + ! -name 'cleanup.cmd' \ + -exec rm -rf {} +