From 9da463eb8ff3bab509e5518d02738cf4cdaab4bc Mon Sep 17 00:00:00 2001 From: Simon Peffers Date: Mon, 22 Jul 2019 13:44:19 -0400 Subject: [PATCH] Create basic vivado testbenches for both example multipliers. Improve documentation. --- .gitignore | 11 +- README.md | 168 ++-- docs/aws_f1.md | 12 +- docs/generate_modulus.md | 9 + docs/interface_timing.png | Bin 0 -> 35405 bytes docs/test_portal.md | 36 + docs/verilator.md | 34 + modular_square/rtl/gen_reduction_lut.py | 208 ++++- modular_square/rtl/modular_square_8_cycles.sv | 8 +- modular_square/rtl/modular_square_simple.sv | 32 +- msu/Makefile | 92 +- msu/rtl/Makefile | 7 +- msu/rtl/Makefile.simple | 96 -- msu/rtl/gen_test.py | 86 ++ msu/rtl/modulus.mk | 36 - msu/rtl/msu.sv | 23 +- msu/rtl/multiplier.mk | 58 ++ msu/rtl/sdaccel/Makefile | 4 +- msu/rtl/sdaccel/Makefile.sdaccel | 21 - msu/rtl/sdaccel/utils.mk | 3 +- msu/rtl/vivado_ozturk/generate.sh | 4 + msu/rtl/vivado_ozturk/msu.srcs/tb.sv | 175 ++++ msu/rtl/vivado_ozturk/msu.tcl | 856 ++++++++++++++++++ msu/rtl/vivado_ozturk/msu.xpr | 532 ----------- msu/rtl/vivado_ozturk/run_vivado.sh | 25 +- msu/rtl/vivado_ozturk/tb_behav.wcfg | 59 ++ msu/rtl/vivado_simple/generate.sh | 4 + .../msu.srcs/constrs_1/new/user.xdc | 9 + msu/rtl/vivado_simple/msu.srcs/tb.sv | 156 ++++ msu/rtl/vivado_simple/msu.tcl | 570 ++++++++++++ msu/rtl/vivado_simple/msu.xpr | 260 ------ msu/rtl/vivado_simple/run_vivado.sh | 28 +- msu/rtl/vivado_simple/tb_behav.wcfg | 47 + msu/sw/MSUVerilatorDirect.cpp | 8 +- 34 files changed, 2516 insertions(+), 1161 deletions(-) create mode 100644 docs/generate_modulus.md create mode 100644 docs/interface_timing.png create mode 100644 docs/test_portal.md create mode 100644 docs/verilator.md delete mode 100644 msu/rtl/Makefile.simple create mode 100755 msu/rtl/gen_test.py delete mode 100644 msu/rtl/modulus.mk create mode 100755 msu/rtl/vivado_ozturk/generate.sh create mode 100644 msu/rtl/vivado_ozturk/msu.srcs/tb.sv create mode 100644 msu/rtl/vivado_ozturk/msu.tcl delete mode 100644 msu/rtl/vivado_ozturk/msu.xpr create mode 100644 msu/rtl/vivado_ozturk/tb_behav.wcfg create mode 100755 msu/rtl/vivado_simple/generate.sh create mode 100644 msu/rtl/vivado_simple/msu.srcs/constrs_1/new/user.xdc create mode 100644 msu/rtl/vivado_simple/msu.srcs/tb.sv create mode 100644 msu/rtl/vivado_simple/msu.tcl delete mode 100644 msu/rtl/vivado_simple/msu.xpr create mode 100644 msu/rtl/vivado_simple/tb_behav.wcfg diff --git a/.gitignore b/.gitignore index 5068020..f6fe879 100644 --- a/.gitignore +++ b/.gitignore @@ -12,13 +12,20 @@ **vivado.log **vivado_pid*.str +msu/rtl/vivado_ozturk/msu +msu/rtl/vivado_ozturk/test.txt msu/rtl/vivado_ozturk/msu.cache msu/rtl/vivado_ozturk/msu.hw msu/rtl/vivado_ozturk/msu.ip_user_files msu/rtl/vivado_ozturk/msu.runs -msu/rtl/vivado_ozturk/msu.srcs +msu/rtl/vivado_ozturk/msu.srcs/mem +msu/rtl/vivado_ozturk/msu.sim + +msu/rtl/vivado_simple/msu +msu/rtl/vivado_simple/test.txt msu/rtl/vivado_simple/msu.cache msu/rtl/vivado_simple/msu.hw msu/rtl/vivado_simple/msu.ip_user_files msu/rtl/vivado_simple/msu.runs -msu/rtl/vivado_simple/msu.srcs +msu/rtl/vivado_simple/msu.srcs/mem +msu/rtl/vivado_simple/msu.sim diff --git a/README.md b/README.md index 67b1675..e0f2e01 100644 --- a/README.md +++ b/README.md @@ -1,110 +1,129 @@ # VDF FPGA Competition Baseline Model -This repository contains the modular squaring multiplier baseline design for the upcoming VDF low latency multiplier competition (stay tuned for more details). The model is designed to be highly parameterized with support for a variety of bit widths. +This repository contains the modular squaring multiplier baseline design for the VDF low latency multiplier FPGA competition. -The algorithm used is a pipelined version of the multiplier developed by Erdinc Ozturk of Sabanci University and described in detail at MIT VDF Day 2019 (). +The goal of the competition is to create the fastest (lowest latency) 1024 bit modular squaring circuit possible targeting the AWS F1 FPGA platform. Up to $100k in prizes is available across two rounds of the competition. For additional detail see **TODO**. -There is also a very simple example using the high level operators (a*a)%N. +## Function -The model is not yet finalized. Expect to see changes leading up the competition start. Please reach out with any questions, comments, or feedback to hello@supranational.net. +The function to optimize is repeated modular squaring over integers. A random input x will be committed at the start of the competition and disclosed at the end of the competition. -# MSU - -The MSU (Modular Squaring Unit) in `msu/rtl` is the top level component of the model. It is an SDAccel RTL Kernel compatible module responsible for interfacing to the outside world through AXI Lite. Internally it instantiates and controls execution of the modular squaring unit. - -The model supports three build targets: - -* Verilator simulation -* Hardware emulation -* FPGA execution - -This document describes the steps required to execute the model on the supported targets. - -# Recommended steps +``` +h = x^(2^t) mod N -## Step 1 - Enable simulation environment +y, N are 1024 bits -Supported OS's are Ubuntu 18 and AWS F1 CentOS. The setup script requires sudo access to install dependencies. +t = 30 +x = random ``` -# Install dependencies -./msu/scripts/simulation_setup.sh -# Run simulations -cd msu -make -``` +## Interface -## Step 2 - Develop your squarer in Python/RTL +The competition uses the AWS F1/Xilinx SDAccel build infrastructure described in [aws_f1](docs/aws_f1.md) to measure performance and functional correctness. If you conform to the following interface your design should function correctly in F1 in the provided software/control infrastructure. -Two squaring circuits are provided as examples, `modular_square/rtl/modular_square_simple.sv` and `modular_square/rtl/modular_square_8_cycles.sv`. You can start from either one. +The interface is shown in [modular_square/rtl/modular_square_simple.sv](modular_square/rtl/modular_square_simple.sv): -Search for "EDIT HERE" to quickly find starting points for editing: ``` -find . -type f -exec grep "EDIT HERE" {} /dev/null \; +module modular_square_simple + #( + parameter int MOD_LEN = 1024 + ) + ( + input logic clk, + input logic reset, + input logic start, + input logic [MOD_LEN-1:0] sq_in, + output logic [MOD_LEN-1:0] sq_out, + output logic valid + ); ``` -There are two testbench environments: -- Direct - the testbdench interacts directly with the squaring circuit. -- MSU - the testbench interacts with the MSU control module. +![Image of interface timing](docs/interface_timing.png) -The Direct testbench provides a simpler environment for developing. +- **MOD_LEN** - Number of bits in the modulus, in this case 1024. +- **reset** - Reset is active high, as recommended by Xilinx design methodologies. +- **start** - A one cycle pulse indicating that sq_in is valid and the computation should start. +- **sq_in** - The initial number to square, which should be captured at the start pulse. +- **sq_out** - The result of the squaring operation. This should be fed back internally to sq_in for repeated squaring. It will be consumed externally at the clock edge trailing the valid signal pulse. +- **valid** - A one cycle pulse indicating that sq_out is valid. -Note the default bitwidth for the simple squarer is 128bits due to verilator limitations. If you start with this design be sure to raise the bitwidth to 1024 in `msu/rtl/Makefile`. +If you have requirements that go beyond this interface, such as loading precomputed values, contact us by email (hello@supranational.net) and we will work with you to determine the best path forward. We are very interested in seeing alternative approaches and algorithms. -You can run simulations for either of the designs: -``` -cd msu +## Baseline models -# Simple squarer -make clean; DIRECT_TB=1 make simple +Two baseline models are provided. You can start from either design. -# 8 cycle Ozturk squarer -make clean; DIRECT_TB=1 make ozturk +**Simple** -# View waveforms -gtkwave rtl/obj_dir/logs/vlt_dump.vcd -``` +See [modular_square/rtl/modular_square_simple.sv](modular_square/rtl/modular_square_simple.sv). This naive design uses high level operators (a*a)%N to do the computation. While not high performance, it simulates correctly, is easy to understand, and can make for a good starting point. -## Step 3 - Synthesize +**Ozturk** -Once you have made changes to the multiplier you can run synthesis to in Vivado, AWS F1, or the test portal to measure and tune performance. +See [modular_square/rtl/modular_square_8_cycles.sv](modular_square/rtl/modular_square_8_cycles.sv). This is an implementation of the multiplier developed by Erdinc Ozturk of Sabanci University and described in detail at [MIT VDF Day 2019](https://dci.mit.edu/video-gallery/2019/5/29/survey-of-hardware-multiplier-techniques-new-innovations-in-low-latency-multipliers-e-ozturk) and in [Modular Multiplication Algorithm Suitable For Low-Latency Circuit Implementations](https://eprint.iacr.org/2019/826). -**_Vivado_** +There are several potential paths for alternative designs and optimizations noted below. -The Vivado GUI makes it easy to try different parameters and visualize results. +## Step 1 - Develop your multiplier -``` -# Simple squarer -cd msu/rtl/vivado_simple -./run_vivado.sh +1. Install [Vivado 2018.3](https://www.xilinx.com/support/download/index.html/content/xilinx/en/downloadNav/vivado-design-tools/2018-3.html). To get started you can use a Xilinx WebPack or 30-day trial license. Extended trial licenses will be made available to registered competitors through Supranational in partnership with Xilinx early in the competition. +1. Depending on your approach choose one of the baseline models to start from. Starting Vivado using the `run_vivado.sh` will automatically generate testbench inputs. -# 8 cycle Ozturk squarer -cd msu/rtl/vivado_ozturk -./run_vivado.sh -``` - -This will launch Vivado with a project configured to build the Ozturk multiplier in out-of-context mode. While not identical to the sdaccel synthesis, it include a pblock that mimics the Shell Logic exclusion are so the results are pretty close. Another pblock forces the latency critical logic to stay in SLR2 for improved performance. - -**Bitwidth**: To test out smaller bitwidths edit the `run_vivado.sh` script. For the Ozturk multiplier be sure to run the script first at 1024 bits to generate the full complement of reduction lookup table files. **If you start with the simple squarer design be sure to increase the bitwidth once you add your multiplier to test at the full 1024 bits.** + **Simple** + ``` + # TO MODIFY: edit modular_square/rtl/modular_square_simple.sv + # + cd msu/rtl/vivado_simple + ./run_vivado.sh + ``` + + **Ozturk** + ``` + # TO MODIFY: edit modular_square/rtl/modular_square_8_cycles.sv + # + cd msu/rtl/vivado_ozturk + ./run_vivado.sh + ``` +1. Run simulations to ensure functional correctness. + * The provided Vivado model includes a basic simulation testbench. + * Run vivado (run_vivado.sh) + * Click Run Simulation->Run Behavioral Simulation + * The test is self checking and should print "SUCCESS". + * The simulation prints cycles per squaring statistics. This, along with synthesis timing results, provides an estimate of latency per squaring. + * You can also use [verilator](docs/verilator.md) if you prefer by running 'cd msu/rtl; make'. No license required. +1. Run out-of-context synthesis + place and route to understand and tune performance. A pblock is set up to mimic the AWS F1 Shell exclusion zone. In our exprience these results are pretty close to what you will get on F1 and and provide an easier/faster/more intuitive interface for improving the design. +1. When you are happy with your design move on to Step 2! -**_AWS F1_** +## Step 2 - SDAccel integration -You can use the AWS cloud to run synthesis for F1. See [aws_f1](docs/aws_f1.md). +Simulation and synthesis/place and route provide a very good performance estimate. The final determination of performance will be based results from the official AWS F1 SDAccel environment. -**_On Premise_** +The reasons to go from from synthesis/simulation, which are (relatively) easy, to running on hardware are: +- Ensure the design functions, fits, performs as expected, etc. in F1, the target platform. +- Test correct functionality with many more iterations by running on FPGA hardware. +- Ensure correct operation when techniques such as false paths, multi-cycle paths, etc. are used. These are very difficult to very in simulation alone. -You can set up an on-premise environment to targeting the AWS F1 platform. See [on-premise](docs/onprem.md). +**SDAccel projected performance** -**_Test portal_** - -TODO: You can submit models to be run on your behalf. +Synthesis/P&R in SDAccel uses automatic frequency scaling to provide feedback on the highest achievable clock frequency. After bitstream generation look for a message like the following in the output logs: +``` +INFO: [XOCC 60-1230] The compiler selected the following frequencies for the +runtime controllable kernel clock(s) and scalable system clock(s): System +(SYSTEM) clock: clk_main_a0 = 250, Kernel (DATA) clock: clk_extra_b0 = 161, +Kernel (KERNEL) clock: clk_extra_c0 = 500 +``` +* This indicates a frequency of 161 MHz for the RTL kernel. +* To estimate squarer latency, multiply the inverse of the frequency by cycles per squaring. Given 8 cycles per squaring, `(1/161)*8*1000 = 49.7ns`. +* Providing clock frequency target guidance to the synthesis tools through the "kernel_frequency" option in `msu/rtl/sdaccel/Makefile.sdaccel` will likely reduce runtime and improve the overall result. -## Step 4 - Hardening +**Testing in SDAccel** -Ultimately the `judge` target must pass to qualify for the competition. It runs simulations, hardware emulation, and synthesis, and bitstream generation. Like synthesis, you can run on-premise, use AWS F1, or use the test portal. +There are three ways to test your design in SDAccel: +1. **Test portal** - The easiest way is to submit your design to the test portal. It will run simulations, hardware emulation, synthesis, and place and route and provide you with a link to the results. You'll need to officially register for the competition and receive a shared secret to submit designs. See [test portal](docs/test_portal.md). **Note we expect this to be operational after the first month of the competition.** +1. **AWS F1** - Instantiate an AWS EC2 F1 development instance and run the flows yourself. See [aws_f1](docs/aws_f1.md). +1. **On-premise** - You can install SDAccel on-premise and run the same flows locally. See [on-premise](docs/onprem.md). -# Optimization Ideas +## Optimization Ideas The following are some potential optimization paths. @@ -112,12 +131,12 @@ The following are some potential optimization paths. * Shorten the pipeline - we believe a 4-5 cycle pipeline is possible with this design * Lengthen the pipeline - insert more pipe stages, run with a faster clock * Change the partial product multiplier size. The DSPs are 26x17 bit multipliers and the modular squaring circuit supports using either by changing a define at the top. -* This design uses lookup tables stored in BlockRAM for the reduction step. These are easy to change to distributed memory and there is support in the model to use UltraRAM. +* This design uses lookup tables stored in BlockRAM for the reduction step. These are easy to change to distributed memory and there is support in the model to use UltraRAM. **TODO - point to a branch with this code** * Optimize the compression trees and accumulators to make the best use of FPGA LUTs and CARRY8 primitives. * Floorplan the design. * Use High Level Synthesis (HLS) or other techniques. -# References +## References Information on VDFs: @@ -132,3 +151,8 @@ AWS online documentation: * SDAccel Docs: * Shell Interface: * Simulating CL Designs: + +## Questions? + +Please reach out with any questions, comments, or feedback through **TODO - channels** + diff --git a/docs/aws_f1.md b/docs/aws_f1.md index d4af89d..ac1be6e 100644 --- a/docs/aws_f1.md +++ b/docs/aws_f1.md @@ -22,12 +22,12 @@ We assume some familiarity with the AWS environment. To instantiate a new AWS ho 1. Choose FPGA Developer AMI 1. For instance type choose z1d.2xlarge for development, f1.2xlarge for FPGA enabled, then Review and Launch 1. For configuration of the host we recommend: - - Increase root disk space by about 20GB for an f1.2xlarge, 60GB for a z1d.2xlarge. - - Add a descriptive tag to help track instances and volumes + 1. Increase root disk space by about 20GB for an f1.2xlarge, 60GB for a z1d.2xlarge. + 1. Add a descriptive tag to help track instances and volumes 1. Launch the instance 1. In the EC2 Instances page, select the instance and choose Actions->Connect. This will tell you the instance hostname that you can ssh to. - - Note that for the FPGA Developer AMI the username will be 'centos' - - Log in with `ssh centos@HOST` + 1. Note that for the FPGA Developer AMI the username will be 'centos' + 1. Log in with `ssh centos@HOST` You may find it convenient to install additional ssh keys for github, etc. @@ -86,12 +86,12 @@ You can enable a **faster run** by relaxing the kernel frequency (search for ker ``` source ./msu/scripts/sdaccel_env.sh -cd msu/rtl/sdaccel +cd msu make clean make hw ``` -Once synthesis successfully completes you can register the new image. Follow the instructions in to setup an S3 bucket. This only needs to be done once. We assume a bucket name 'vdfsn' but you will need to change this to match your bucket name. Once that is done run the following: +Once synthesis successfully completes you can register the new image to process it for running on FPGA hardware. Follow the instructions in to setup an S3 bucket. This only needs to be done once. We assume a bucket name 'vdfsn' but you will need to change this to match your bucket name. Once that is done run the following: ``` # Configure AWS credentials. You should only need to do this once on a given diff --git a/docs/generate_modulus.md b/docs/generate_modulus.md new file mode 100644 index 0000000..a7b81bf --- /dev/null +++ b/docs/generate_modulus.md @@ -0,0 +1,9 @@ + +To generate a new RSA modulus: +``` +openssl genrsa -out mykey.pem 1024 +openssl rsa -in mykey.pem -pubout > mykey.pub +openssl rsa -pubin -modulus -noout -in mykey.pub +rm mykey.pem +rm mykey.pub +``` diff --git a/docs/interface_timing.png b/docs/interface_timing.png new file mode 100644 index 0000000000000000000000000000000000000000..b89a702c9ce22ffa8eb0d59f23bcc5ba2684b959 GIT binary patch literal 35405 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�q?xfy{w|f`UrsN+pF!;STpxc|0UB7B5!uv%)VJ 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 S<+crE00K`}KbLh*2~7a9oIVEt literal 0 HcmV?d00001 diff --git a/docs/test_portal.md b/docs/test_portal.md new file mode 100644 index 0000000..4c962a8 --- /dev/null +++ b/docs/test_portal.md @@ -0,0 +1,36 @@ +# Test portal + +The online test portal dramatically lowers the bar to testing your design in AWS F1 environment. + +Rather than go through the process of enabling AWS, the F1 environment, etc., you can design, test and tune your multiplier and Vivado and submit it to the portal to make sure the results are what you expect. + +Once you submit your design, the test portal will clone your repo, run simulation, hardware emulation, synthesis/place and route, and provide the results back to you in an encrypted file on S3. + +## Usage limitations + +- The portal is not intended for basic testing - you should test and tune your design in Vivado first. +- The script will schedule requests prevent spamming and provide a level of access/fairness to the teams +- There will be a time limit of 8 hours for any request. We'll revise this if needed based on usage data. The goal is to balance allowing jobs to complete with fairness and availability to all teams. + +## API + +Usage: msu/scripts/portal --access KEY [command] + +- --access - secret access key, issued per team. This is a hash of the encryption key. +- command + - list - display pending jobs + - cancel JOBID - cancel a job + - submit repo [options] - submit a repo for processing + - --sim - run simulations + - --hw-emu - run hardware emulation + - --synthesis - run synthesis/pnr + - --email - notification email address + - Each stage runs all preceeding stages + +## Job flow + +1. The API endpoint will validate the request and use the secret key to authorize the transaction. +1. Once the job is scheduled the endpoint will dispatch it to a worker, which may be a long running instance, AWS Batch, or some other mechanism. +1. The worker will instantiate a docker image on a z1d.2xlarge, setup the F1 environment, and run the job. +1. The worker will gather the results, including log files and reports, create a tarball, and encrypt it with a randomly generated password. +1. The worker will publish the results on a shared S3 node and send an email notification. diff --git a/docs/verilator.md b/docs/verilator.md new file mode 100644 index 0000000..156d436 --- /dev/null +++ b/docs/verilator.md @@ -0,0 +1,34 @@ +# Verilator + +The Ozturk design supports verilator as a simulator. + +While we're big fans of verilator, it unfortunately doesn't support 1024 bit modular squaring using * and %. As a result the default bitwidth for this design when using verilator is 128 bits. We found it can also be finicky with large bitwidths. Unpacked arrays of + +Enabling verilator takes just a few steps on Ubuntu 18 and AWS F1 CentOS. The setup script requires sudo access to install dependencies. + +``` +# Install dependencies +./msu/scripts/simulation_setup.sh + +# Run simulations for both designs +cd msu +make +``` + +The verilator testbench instantiates the MSU portion of the design as well as the squarer circuit. The MSU interfaces to the SDAccel interfaces and provides control to count the number iterations, capture the result, and send it back to the host driver. + +Simulating the MSU design is a fast way to iterate, debug, and test before moving on to hardware emulation. + +You can run simulations and view waveforms for a particular design as follows: +``` +cd msu + +# Simple squarer +make clean; make simple + +# 8 cycle Ozturk squarer +make clean; make ozturk + +# View waveforms +gtkwave rtl/obj_dir/logs/vlt_dump.vcd +``` diff --git a/modular_square/rtl/gen_reduction_lut.py b/modular_square/rtl/gen_reduction_lut.py index ba1123c..61a0f5a 100755 --- a/modular_square/rtl/gen_reduction_lut.py +++ b/modular_square/rtl/gen_reduction_lut.py @@ -27,6 +27,7 @@ NUM_SEGMENTS = 4 WORD_LEN = 16 EXTRA_ELEMENTS = 2 +NUM_URAM = 0 # TODO - we probably don't need these hardcoded values anymore if (NONREDUNDANT_ELEMENTS == 128): @@ -37,16 +38,16 @@ try: opts, args = getopt.getopt(sys.argv[1:],"hM:r:n:w:", \ ["modulus=","redundant=", \ - "nonredundant=", "wordlen="]) + "nonredundant=", "wordlen=", "urams="]) except getopt.GetoptError: print ('gen_reduction_lut.py -M -r ', \ - '-nr -wl ') + '-nr -wl -u ') sys.exit(2) for opt, arg in opts: if opt == '-h': print ('gen_reduction_lut.py -M -r ', \ - '-nr -wl ') + '-nr -wl -u ') sys.exit() elif opt in ("-M", "--modulus"): M = int(arg) @@ -56,6 +57,8 @@ NONREDUNDANT_ELEMENTS = int(arg) elif opt in ("-w", "--wordlen"): WORD_LEN = int(arg) + elif opt in ("-u", "--urams"): + NUM_URAM = int(arg) print () print ('Parameter Values') @@ -78,6 +81,11 @@ LUT_SIZE = 2**LOOK_UP_WIDTH LUT_WIDTH = WORD_LEN * NONREDUNDANT_ELEMENTS; +# Sanitize URAM and BRAM counts +if NUM_URAM > LUT_NUM_ELEMENTS - 1: + NUM_URAM = LUT_NUM_ELEMENTS - 1 +NUM_BRAM = LUT_NUM_ELEMENTS - NUM_URAM + ################################################################################ # Compute the reduction tables ################################################################################ @@ -119,7 +127,7 @@ f = open('reduction_lut.sv', 'w') -top = \ +emit = \ '''/******************************************************************************* Copyright 2019 Supranational LLC @@ -143,6 +151,7 @@ parameter int NUM_SEGMENTS = 4, parameter int WORD_LEN = 16, parameter int BIT_LEN = 17, + parameter int DIN_LEN = 8, parameter int NUM_ELEMENTS = REDUNDANT_ELEMENTS+ NONREDUNDANT_ELEMENTS, @@ -159,49 +168,176 @@ input logic [LOOK_UP_WIDTH:0] lut_addr[LUT_NUM_ELEMENTS], input logic shift_high, input logic shift_overflow, - output logic [BIT_LEN-1:0] lut_data[NUM_ELEMENTS][LUT_NUM_ELEMENTS] + output logic [BIT_LEN-1:0] lut_data[NUM_ELEMENTS][LUT_NUM_ELEMENTS], +''' +f.write(emit) + +if NUM_URAM == 0: + f.write("/* verilator lint_off UNUSED */") + +emit = \ +''' + input we, + input [DIN_LEN-1:0] din, + input din_valid +''' +f.write(emit) + +if NUM_URAM == 0: + f.write("/* verilator lint_on UNUSED */") + +emit = \ +''' ); // There is twice as many entries due to low and high values localparam int NUM_LUT_ENTRIES = 2**(LOOK_UP_WIDTH+1); localparam int LUT_WIDTH = WORD_LEN * NONREDUNDANT_ELEMENTS; - localparam int FULL_WIDTH = WORD_LEN * NUM_ELEMENTS; - logic [FULL_WIDTH-1:0] lut_read_data[LUT_NUM_ELEMENTS]; + localparam int NUM_URAM = %(NUM_URAM)s; + localparam int NUM_BRAM = LUT_NUM_ELEMENTS-NUM_URAM; + localparam int XFERS_PER_URAM = (LUT_WIDTH*NUM_LUT_ENTRIES)/DIN_LEN; + + logic [LUT_WIDTH-1:0] lut_read_data[LUT_NUM_ELEMENTS]; +''' +f.write(emit % {'NUM_URAM':NUM_URAM}) + +########################################################################## +# URAM Only +########################################################################## + +if NUM_URAM > 0: + f.write(" logic [LUT_WIDTH-1:0] lut_read_data_uram[NUM_URAM];") + + emit = \ +''' + logic [NUM_URAM-1:0] we_uram; + genvar i; + generate + for(i = 0; i < NUM_URAM; i++) begin : urams + uram_wide #(.DATA_LEN(NONREDUNDANT_ELEMENTS*WORD_LEN), + .ADDR_LEN(LOOK_UP_WIDTH+1), + .DIN_LEN(DIN_LEN) + ) + u1(.clk(clk), + .we(we_uram[i] && we), + .din(din), + .din_valid(din_valid), + .addr(lut_addr[i]), + .dout(lut_read_data_uram[i])); + end + endgenerate + + // Enable writing data into the URAMs + logic [$clog2(XFERS_PER_URAM):0] write_uram_xfers; + always_ff @(posedge clk) begin + if(!we) begin + we_uram <= {{(NUM_URAM-1){1'b0}}, 1'b1}; + write_uram_xfers <= XFERS_PER_URAM[$clog2(XFERS_PER_URAM):0]; + end else if(|we_uram && din_valid) begin + if(write_uram_xfers == 1) begin + we_uram <= we_uram << 1; + write_uram_xfers <= XFERS_PER_URAM[$clog2(XFERS_PER_URAM):0]; + end else begin + write_uram_xfers <= write_uram_xfers - 1; + end + end + end +''' + f.write(emit) + + +########################################################################## +# BRAM Only +########################################################################## + +if NUM_BRAM > 0: + f.write(" logic [LUT_WIDTH-1:0] lut_read_data_bram[NUM_BRAM];") + + emit = \ +''' logic [BIT_LEN-1:0] lut_output[NUM_ELEMENTS][LUT_NUM_ELEMENTS]; + // Delay to align with data from memory + logic shift_high_1d; + logic shift_overflow_1d; + + always_ff @(posedge clk) begin + shift_high_1d <= shift_high; + shift_overflow_1d <= shift_overflow; + end ''' -f.write(top) + f.write(emit) -block_str = ' (* rom_style = "block" *) logic [LUT_WIDTH-1:0] lut_{0:03d}[NUM_LUT_ENTRIES];\n' + block_str = ' (* rom_style = "block" *) logic [LUT_WIDTH-1:0] lut_{0:03d}[NUM_LUT_ENTRIES];\n' -for i in range (LUT_NUM_ELEMENTS): - f.write(block_str.format(i)) + for i in range (NUM_BRAM): + f.write(block_str.format(i+NUM_URAM)) -read_str = ' $readmemh("reduction_lut_{0:03d}.dat", lut_{0:03d});\n' + read_str = ' $readmemh("reduction_lut_{0:03d}.dat", lut_{0:03d});\n' -f.write('\n initial begin\n') -for i in range (LUT_NUM_ELEMENTS): - f.write(read_str.format(i)) -f.write(' end\n') + f.write('\n initial begin\n') + for i in range (NUM_BRAM): + f.write(read_str.format(i+NUM_URAM)) + f.write(' end\n') -assign_str = ' lut_read_data[{0:d}] = {{{{FULL_WIDTH-LUT_WIDTH{{1\'b0}}}},\n\ - lut_{0:03d}[lut_addr[{0:d}]][LUT_WIDTH-1:0]}};\n' -f.write('\n always_comb begin\n') -for i in range (LUT_NUM_ELEMENTS): - f.write(assign_str.format(i)) -f.write(' end\n') + #assign_str = ' lut_read_data[{0:d}] <= lut_{0:03d}[lut_addr[{0:d}]][LUT_WIDTH-1:0];\n' + assign_str = ' lut_read_data_bram[{0:d}] <= lut_{1:03d}[lut_addr[{1:d}]];\n' + f.write('\n always_ff @(posedge clk) begin\n') + for i in range (NUM_BRAM): + f.write(assign_str.format(i, i+NUM_URAM)) + f.write(' end\n') -bottom = \ +########################################################################## +# Mixed URAM/BRAM +########################################################################## + +emit = \ ''' + + // Read data out of the memories always_comb begin +''' +f.write(emit) + +emit = \ +''' + for (int k=0; k 0: + f.write(emit) + +emit = \ +''' + for (int k=0; k 0: + f.write(emit) + + +emit = \ +''' + end + + always_comb begin + for (int k=0; k msuconfig.vh + echo "\`define SQ_OUT_BITS_DEF $(SQ_OUT_BITS)" \ + >> msuconfig.vh + echo "\`define MODULUS_DEF $(MOD_LEN)'d$(MODULUS)" \ + >> msuconfig.vh + echo "\`define MOD_LEN_DEF $(MOD_LEN)" \ + >> msuconfig.vh +ifeq ($(SIMPLE_SQ), 1) + echo "\`define SIMPLE_SQ $(SIMPLE_SQ)" \ + >> msuconfig.vh +endif + +mem/reduction_lut_000.dat: + mkdir -p mem + cd mem && $(MODSQR_DIR)/rtl/gen_reduction_lut.py \ + --nonredundant $(NONREDUNDANT_ELEMENTS) \ + --modulus $(MODULUS) diff --git a/msu/rtl/sdaccel/Makefile b/msu/rtl/sdaccel/Makefile index 6aaac0c..834061b 100644 --- a/msu/rtl/sdaccel/Makefile +++ b/msu/rtl/sdaccel/Makefile @@ -14,7 +14,7 @@ # limitations under the License. # -OBJ=obj +OBJ ?= obj # Build the simulation model plus the host. To rebuild the RTL # after making changes you must 'make clean' first. @@ -51,4 +51,6 @@ ifdef XILINX_SDX $(MAKE) -C $(OBJ) -f ../Makefile.sdaccel cleanall endif rm -fr $(OBJ) + rm -fr $(OBJ)_hw_emu + rm -fr $(OBJ)_hw diff --git a/msu/rtl/sdaccel/Makefile.sdaccel b/msu/rtl/sdaccel/Makefile.sdaccel index 13738ef..108a000 100755 --- a/msu/rtl/sdaccel/Makefile.sdaccel +++ b/msu/rtl/sdaccel/Makefile.sdaccel @@ -24,8 +24,6 @@ include ../../multiplier.mk HOST_FLAGS_HW_EMU = -e -f 1 HOST_FLAGS_FPGA = -e -f 10 -include ../../modulus.mk - ############################################################################ # Synthesis directives ############################################################################ @@ -186,29 +184,10 @@ $(BINARY_CONTAINER_AWS): $(BINARY_CONTAINER) -s3_bucket=$(S3_BUCKET) -s3_dcp_key=dcp -s3_logs_key=logs cat *afi_id.txt -# Configure MSU parameters. These are included through vdf_kernel.sv -msuconfig.vh: - echo "\`define SQ_IN_BITS_DEF $(SQ_IN_BITS)" \ - > msuconfig.vh - echo "\`define SQ_OUT_BITS_DEF $(SQ_OUT_BITS)" \ - >> msuconfig.vh - echo "\`define MODULUS_DEF $(MOD_LEN)'d$(MODULUS)" \ - >> msuconfig.vh - echo "\`define MOD_LEN_DEF $(MOD_LEN)" \ - >> msuconfig.vh -ifeq ($(SIMPLE_SQ), 1) - echo "\`define SIMPLE_SQ $(SIMPLE_SQ)" \ - >> msuconfig.vh -endif # Generate the LUTs. reduction_lut_000.dat will be present for any bitwidth. $(BINARY_CONTAINER_XO): mem/reduction_lut_000.dat $(BINARY_CONTAINER_XO): msuconfig.vh -mem/reduction_lut_000.dat: - mkdir -p mem - cd mem && $(MODSQR_DIR)/rtl/gen_reduction_lut.py \ - --nonredundant $(NONREDUNDANT_ELEMENTS) \ - --modulus $(MODULUS) sdaccel.ini: ifeq ($(TRACE), 1) diff --git a/msu/rtl/sdaccel/utils.mk b/msu/rtl/sdaccel/utils.mk index e0f4722..5957533 100755 --- a/msu/rtl/sdaccel/utils.mk +++ b/msu/rtl/sdaccel/utils.mk @@ -26,7 +26,8 @@ endif #Checks for XILINX_SDX ifndef XILINX_SDX -$(error XILINX_SDX variable is not set, please set correctly and rerun) +$(warning XILINX_SDX variable is not set, please set correctly and rerun) +$(error source msu/scripts/sdaccel_env.sh) endif # sanitize_dsa - create a filesystem friendly name from dsa name diff --git a/msu/rtl/vivado_ozturk/generate.sh b/msu/rtl/vivado_ozturk/generate.sh new file mode 100755 index 0000000..e841d22 --- /dev/null +++ b/msu/rtl/vivado_ozturk/generate.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +vivado -source msu.tcl -mode batch + diff --git a/msu/rtl/vivado_ozturk/msu.srcs/tb.sv b/msu/rtl/vivado_ozturk/msu.srcs/tb.sv new file mode 100644 index 0000000..edb4c27 --- /dev/null +++ b/msu/rtl/vivado_ozturk/msu.srcs/tb.sv @@ -0,0 +1,175 @@ +/******************************************************************************* + Copyright 2019 Supranational LLC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*******************************************************************************/ + +`include "msuconfig.vh" + +module tb(); + localparam integer MOD_LEN = 1024; + //localparam integer MOD_LEN = 128; + + // Ozturk parameters + localparam integer WORD_LEN = 16; + localparam integer BIT_LEN = 17; + localparam integer AXI_LEN = 32; + localparam integer SQ_IN_BITS = `SQ_IN_BITS_DEF; + localparam integer SQ_OUT_BITS = `SQ_OUT_BITS_DEF; + localparam MODULUS = `MODULUS_DEF; + + + logic clk; + logic reset; + logic start; + logic valid; + logic [MOD_LEN-1:0] modulus; + logic [SQ_IN_BITS-1:0] sq_in; + logic [SQ_OUT_BITS-1:0] sq_out; + logic [MOD_LEN-1:0] sq_out_expected; + logic [SQ_OUT_BITS-1:0] sq_out_actual; + logic [SQ_OUT_BITS-1:0] sq_out_reducing; + logic [MOD_LEN-1:0] sq_out_reduced; + + integer t_start; + integer t_final; + integer t_curr; + + integer test_file; + integer i, ret; + integer cycle_count; + integer error_count; + + integer total_cycle_count; + integer total_squarings; + + modular_square_wrapper + #( + .MOD_LEN(MOD_LEN) + ) + uut( + clk, + reset, + start, + sq_in, + sq_out, + valid + ); + + initial begin + test_file = $fopen("../../../../../test.txt", "r"); + if(test_file == 0) begin + $display("test_file handle was NULL"); + $finish; + end + end + + always begin + #5 clk = ~clk; + end + + initial begin + // Reset the design + clk = 1'b0; + reset = 1'b1; + sq_in = 0; + start = 1'b0; + t_start = 0; + t_curr = 0; + + @(negedge clk); + @(negedge clk); + @(negedge clk); + @(negedge clk); + + reset = 1'b0; + + @(negedge clk); + @(negedge clk); + @(negedge clk); + @(negedge clk); + + // Scan in the modulus and initial value + $fscanf(test_file, "%x\n", sq_in); + @(negedge clk); + + start = 1'b1; + @(negedge clk); + start = 1'b0; + + // Run the squarer and periodically check results + error_count = 0; + total_cycle_count = 0; + total_squarings = 0; + while(1) begin + ret = $fscanf(test_file, "%d, %x\n", t_final, sq_out_expected); + if(ret != 2) begin + break; + end + + // Run to the next checkpoint specified in the test file + cycle_count = 1; + t_start = t_curr; + while(t_curr < t_final) begin + if(valid == 1'b1) begin + t_curr = t_curr + 1; + sq_out_actual = sq_out; + total_squarings = total_squarings + 1; + end + + @(negedge clk); + cycle_count = cycle_count + 1; + total_cycle_count = total_cycle_count + 1; + end + + // Reduce the result from polynomial form + sq_out_reducing = 0; + for(i = 0; i < SQ_OUT_BITS / AXI_LEN; i++) begin + if(i > 0) begin + sq_out_reducing <<= WORD_LEN; + sq_out_actual <<= AXI_LEN; + end + sq_out_reducing += sq_out_actual[SQ_OUT_BITS-AXI_LEN +: BIT_LEN]; + end + sq_out_reduced = sq_out_reducing % MODULUS; + + $display("%5d %0.2f %x", t_final, + real'(cycle_count) / real'(t_final - t_start), + sq_out_reduced); + + // Check correctness + if(sq_out_reduced !== sq_out_expected) begin + $display("MISTATCH expected %x", sq_out_expected); + $display(" actual %x", sq_out_reduced); + error_count = error_count + 1; + break; + end + @(negedge clk); + total_cycle_count = total_cycle_count + 1; + end + $display("Overall %d cycles, %d squarings, %0.2f cyc/sq", + total_cycle_count, total_squarings, + real'(total_cycle_count) / real'(total_squarings)); + if(error_count == 0) begin + $display("SUCCESS!"); + $finish(); + end + @(negedge clk); + @(negedge clk); + @(negedge clk); + @(negedge clk); + $error("FAILURE %d mismatches", error_count); + $finish(); + end +endmodule + diff --git a/msu/rtl/vivado_ozturk/msu.tcl b/msu/rtl/vivado_ozturk/msu.tcl new file mode 100644 index 0000000..cb1e327 --- /dev/null +++ b/msu/rtl/vivado_ozturk/msu.tcl @@ -0,0 +1,856 @@ +#***************************************************************************************** +# Vivado (TM) v2018.3 (64-bit) +# +# msu.tcl: Tcl script for re-creating project 'msu' +# +# Generated by Vivado on Thu Jul 25 21:12:36 EDT 2019 +# IP Build 2404404 on Fri Dec 7 01:43:56 MST 2018 +# +# This file contains the Vivado Tcl commands for re-creating the project to the state* +# when this script was generated. In order to re-create the project, please source this +# file in the Vivado Tcl Shell. +# +# * Note that the runs in the created project will be configured the same way as the +# original project, however they will not be launched automatically. To regenerate the +# run results please launch the synthesis/implementation runs as needed. +# +#***************************************************************************************** +# NOTE: In order to use this script for source control purposes, please make sure that the +# following files are added to the source control system:- +# +# 1. This project restoration tcl script (msu.tcl) that was generated. +# +# 2. The following source(s) files that were local or imported into the original project. +# (Please see the '$orig_proj_dir' and '$origin_dir' variable setting below at the start of the script) +# +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/vivado_ozturk/msu.srcs/msuconfig.vh" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/vivado_ozturk/msu.srcs/mem/reduction_lut.sv" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/vivado_ozturk/msu.srcs/mem/reduction_lut_020.dat" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/vivado_ozturk/msu.srcs/mem/reduction_lut_012.dat" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/vivado_ozturk/msu.srcs/mem/reduction_lut_004.dat" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/vivado_ozturk/msu.srcs/mem/reduction_lut_017.dat" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/vivado_ozturk/msu.srcs/mem/reduction_lut_009.dat" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/vivado_ozturk/msu.srcs/mem/reduction_lut_033.dat" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/vivado_ozturk/msu.srcs/mem/reduction_lut_024.dat" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/vivado_ozturk/msu.srcs/mem/reduction_lut_026.dat" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/vivado_ozturk/msu.srcs/mem/reduction_lut_011.dat" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/vivado_ozturk/msu.srcs/mem/reduction_lut_000.dat" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/vivado_ozturk/msu.srcs/mem/reduction_lut_029.dat" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/vivado_ozturk/msu.srcs/mem/reduction_lut_013.dat" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/vivado_ozturk/msu.srcs/mem/reduction_lut_030.dat" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/vivado_ozturk/msu.srcs/mem/reduction_lut_007.dat" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/vivado_ozturk/msu.srcs/mem/reduction_lut_034.dat" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/vivado_ozturk/msu.srcs/mem/reduction_lut_008.dat" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/vivado_ozturk/msu.srcs/mem/reduction_lut_016.dat" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/vivado_ozturk/msu.srcs/mem/reduction_lut_021.dat" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/vivado_ozturk/msu.srcs/mem/reduction_lut_003.dat" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/vivado_ozturk/msu.srcs/mem/reduction_lut_025.dat" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/vivado_ozturk/msu.srcs/mem/reduction_lut_001.dat" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/vivado_ozturk/msu.srcs/mem/reduction_lut_006.dat" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/vivado_ozturk/msu.srcs/mem/reduction_lut_031.dat" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/vivado_ozturk/msu.srcs/mem/reduction_lut_019.dat" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/vivado_ozturk/msu.srcs/mem/reduction_lut_028.dat" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/vivado_ozturk/msu.srcs/mem/reduction_lut_022.dat" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/vivado_ozturk/msu.srcs/mem/reduction_lut_015.dat" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/vivado_ozturk/msu.srcs/mem/reduction_lut_035.dat" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/vivado_ozturk/msu.srcs/mem/reduction_lut_018.dat" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/vivado_ozturk/msu.srcs/mem/reduction_lut_005.dat" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/vivado_ozturk/msu.srcs/mem/reduction_lut_002.dat" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/vivado_ozturk/msu.srcs/mem/reduction_lut_032.dat" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/vivado_ozturk/msu.srcs/mem/reduction_lut_014.dat" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/vivado_ozturk/msu.srcs/mem/reduction_lut_027.dat" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/vivado_ozturk/msu.srcs/mem/reduction_lut_010.dat" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/vivado_ozturk/msu.srcs/mem/reduction_lut_023.dat" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/vivado_ozturk/msu.srcs/constrs_1/new/user.xdc" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/vivado_ozturk/msu.srcs/tb.sv" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/vivado_ozturk/tb_behav.wcfg" +# +# 3. The following remote source files that were added to the original project:- +# +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/sdaccel/vdf_control_s_axi.v" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/primitives/rtl/carry_save_adder.sv" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/primitives/rtl/carry_save_adder_tree_level.sv" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/primitives/rtl/compressor_tree_3_to_2.sv" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/primitives/rtl/full_adder.sv" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/modular_square/rtl/modular_square_8_cycles.sv" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/modular_square_wrapper.sv" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/msu.sv" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/primitives/rtl/multiplier.sv" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/primitives/rtl/multiply.sv" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/sdaccel/vdf_axi_read_master.sv" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/sdaccel/vdf_axi_write_master.sv" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/sdaccel/vdf_counter.sv" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/sdaccel/vdf_kernel.sv" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/sdaccel/vdf_wrapper.sv" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev2/msu/rtl/sdaccel/vdf.v" +# +#***************************************************************************************** + +# Set the reference directory for source file relative paths (by default the value is script directory path) +set origin_dir "." + +# Use origin directory path location variable, if specified in the tcl shell +if { [info exists ::origin_dir_loc] } { + set origin_dir $::origin_dir_loc +} + +# Set the project name +set _xil_proj_name_ "msu" + +# Use project name variable, if specified in the tcl shell +if { [info exists ::user_project_name] } { + set _xil_proj_name_ $::user_project_name +} + +variable script_file +set script_file "msu.tcl" + +# Help information for this script +proc print_help {} { + variable script_file + puts "\nDescription:" + puts "Recreate a Vivado project from this script. The created project will be" + puts "functionally equivalent to the original project for which this script was" + puts "generated. The script contains commands for creating a project, filesets," + puts "runs, adding/importing sources and setting properties on various objects.\n" + puts "Syntax:" + puts "$script_file" + puts "$script_file -tclargs \[--origin_dir \]" + puts "$script_file -tclargs \[--project_name \]" + puts "$script_file -tclargs \[--help\]\n" + puts "Usage:" + puts "Name Description" + puts "-------------------------------------------------------------------------" + puts "\[--origin_dir \] Determine source file paths wrt this path. Default" + puts " origin_dir path value is \".\", otherwise, the value" + puts " that was set with the \"-paths_relative_to\" switch" + puts " when this script was generated.\n" + puts "\[--project_name \] Create project with the specified name. Default" + puts " name is the name of the project from where this" + puts " script was generated.\n" + puts "\[--help\] Print help information for this script" + puts "-------------------------------------------------------------------------\n" + exit 0 +} + +if { $::argc > 0 } { + for {set i 0} {$i < $::argc} {incr i} { + set option [string trim [lindex $::argv $i]] + switch -regexp -- $option { + "--origin_dir" { incr i; set origin_dir [lindex $::argv $i] } + "--project_name" { incr i; set _xil_proj_name_ [lindex $::argv $i] } + "--help" { print_help } + default { + if { [regexp {^-} $option] } { + puts "ERROR: Unknown option '$option' specified, please type '$script_file -tclargs --help' for usage info.\n" + return 1 + } + } + } + } +} + +# Set the directory path for the original project from where this script was exported +set orig_proj_dir "[file normalize "$origin_dir/"]" + +# Create project +create_project ${_xil_proj_name_} ./${_xil_proj_name_} -part xcvu9p-flga2104-2L-e + +# Set the directory path for the new project +set proj_dir [get_property directory [current_project]] + +# Set project properties +set obj [current_project] +set_property -name "board_part" -value "xilinx.com:vcu118:part0:2.0" -objects $obj +set_property -name "board_part_repo_paths" -value "/home/snpeffer/src/vdf/artya7/vivado-boards-master/new/board_files" -objects $obj +set_property -name "default_lib" -value "xil_defaultlib" -objects $obj +set_property -name "dsa.accelerator_binary_content" -value "bitstream" -objects $obj +set_property -name "dsa.accelerator_binary_format" -value "xclbin2" -objects $obj +set_property -name "dsa.board_id" -value "vcu118" -objects $obj +set_property -name "dsa.description" -value "Vivado generated DSA" -objects $obj +set_property -name "dsa.dr_bd_base_address" -value "0" -objects $obj +set_property -name "dsa.emu_dir" -value "emu" -objects $obj +set_property -name "dsa.flash_interface_type" -value "bpix16" -objects $obj +set_property -name "dsa.flash_offset_address" -value "0" -objects $obj +set_property -name "dsa.flash_size" -value "1024" -objects $obj +set_property -name "dsa.host_architecture" -value "x86_64" -objects $obj +set_property -name "dsa.host_interface" -value "pcie" -objects $obj +set_property -name "dsa.num_compute_units" -value "60" -objects $obj +set_property -name "dsa.platform_state" -value "pre_synth" -objects $obj +set_property -name "dsa.vendor" -value "xilinx" -objects $obj +set_property -name "dsa.version" -value "0.0" -objects $obj +set_property -name "enable_vhdl_2008" -value "1" -objects $obj +set_property -name "ip_cache_permissions" -value "read write" -objects $obj +set_property -name "ip_output_repo" -value "$proj_dir/${_xil_proj_name_}.cache/ip" -objects $obj +set_property -name "mem.enable_memory_map_generation" -value "1" -objects $obj +set_property -name "sim.central_dir" -value "$proj_dir/${_xil_proj_name_}.ip_user_files" -objects $obj +set_property -name "sim.ip.auto_export_scripts" -value "1" -objects $obj +set_property -name "simulator_language" -value "Mixed" -objects $obj +set_property -name "webtalk.xsim_launch_sim" -value "33" -objects $obj + +# Create 'sources_1' fileset (if not found) +if {[string equal [get_filesets -quiet sources_1] ""]} { + create_fileset -srcset sources_1 +} + +# Set 'sources_1' fileset object +set obj [get_filesets sources_1] +set files [list \ + [file normalize "${origin_dir}/../sdaccel/vdf_control_s_axi.v"] \ + [file normalize "${origin_dir}/../../../primitives/rtl/carry_save_adder.sv"] \ + [file normalize "${origin_dir}/../../../primitives/rtl/carry_save_adder_tree_level.sv"] \ + [file normalize "${origin_dir}/../../../primitives/rtl/compressor_tree_3_to_2.sv"] \ + [file normalize "${origin_dir}/../../../primitives/rtl/full_adder.sv"] \ + [file normalize "${origin_dir}/../../../modular_square/rtl/modular_square_8_cycles.sv"] \ + [file normalize "${origin_dir}/../modular_square_wrapper.sv"] \ + [file normalize "${origin_dir}/../msu.sv"] \ + [file normalize "${origin_dir}/../../../primitives/rtl/multiplier.sv"] \ + [file normalize "${origin_dir}/../../../primitives/rtl/multiply.sv"] \ + [file normalize "${origin_dir}/../sdaccel/vdf_axi_read_master.sv"] \ + [file normalize "${origin_dir}/../sdaccel/vdf_axi_write_master.sv"] \ + [file normalize "${origin_dir}/../sdaccel/vdf_counter.sv"] \ + [file normalize "${origin_dir}/../sdaccel/vdf_kernel.sv"] \ + [file normalize "${origin_dir}/../sdaccel/vdf_wrapper.sv"] \ + [file normalize "${origin_dir}/../sdaccel/vdf.v"] \ +] +add_files -norecurse -fileset $obj $files + +# Add local files from the original project (-no_copy_sources specified) +set files [list \ + [file normalize "${origin_dir}/msu.srcs/msuconfig.vh" ]\ + [file normalize "${origin_dir}/msu.srcs/mem/reduction_lut.sv" ]\ + [file normalize "${origin_dir}/msu.srcs/mem/reduction_lut_020.dat" ]\ + [file normalize "${origin_dir}/msu.srcs/mem/reduction_lut_012.dat" ]\ + [file normalize "${origin_dir}/msu.srcs/mem/reduction_lut_004.dat" ]\ + [file normalize "${origin_dir}/msu.srcs/mem/reduction_lut_017.dat" ]\ + [file normalize "${origin_dir}/msu.srcs/mem/reduction_lut_009.dat" ]\ + [file normalize "${origin_dir}/msu.srcs/mem/reduction_lut_033.dat" ]\ + [file normalize "${origin_dir}/msu.srcs/mem/reduction_lut_024.dat" ]\ + [file normalize "${origin_dir}/msu.srcs/mem/reduction_lut_026.dat" ]\ + [file normalize "${origin_dir}/msu.srcs/mem/reduction_lut_011.dat" ]\ + [file normalize "${origin_dir}/msu.srcs/mem/reduction_lut_000.dat" ]\ + [file normalize "${origin_dir}/msu.srcs/mem/reduction_lut_029.dat" ]\ + [file normalize "${origin_dir}/msu.srcs/mem/reduction_lut_013.dat" ]\ + [file normalize "${origin_dir}/msu.srcs/mem/reduction_lut_030.dat" ]\ + [file normalize "${origin_dir}/msu.srcs/mem/reduction_lut_007.dat" ]\ + [file normalize "${origin_dir}/msu.srcs/mem/reduction_lut_034.dat" ]\ + [file normalize "${origin_dir}/msu.srcs/mem/reduction_lut_008.dat" ]\ + [file normalize "${origin_dir}/msu.srcs/mem/reduction_lut_016.dat" ]\ + [file normalize "${origin_dir}/msu.srcs/mem/reduction_lut_021.dat" ]\ + [file normalize "${origin_dir}/msu.srcs/mem/reduction_lut_003.dat" ]\ + [file normalize "${origin_dir}/msu.srcs/mem/reduction_lut_025.dat" ]\ + [file normalize "${origin_dir}/msu.srcs/mem/reduction_lut_001.dat" ]\ + [file normalize "${origin_dir}/msu.srcs/mem/reduction_lut_006.dat" ]\ + [file normalize "${origin_dir}/msu.srcs/mem/reduction_lut_031.dat" ]\ + [file normalize "${origin_dir}/msu.srcs/mem/reduction_lut_019.dat" ]\ + [file normalize "${origin_dir}/msu.srcs/mem/reduction_lut_028.dat" ]\ + [file normalize "${origin_dir}/msu.srcs/mem/reduction_lut_022.dat" ]\ + [file normalize "${origin_dir}/msu.srcs/mem/reduction_lut_015.dat" ]\ + [file normalize "${origin_dir}/msu.srcs/mem/reduction_lut_035.dat" ]\ + [file normalize "${origin_dir}/msu.srcs/mem/reduction_lut_018.dat" ]\ + [file normalize "${origin_dir}/msu.srcs/mem/reduction_lut_005.dat" ]\ + [file normalize "${origin_dir}/msu.srcs/mem/reduction_lut_002.dat" ]\ + [file normalize "${origin_dir}/msu.srcs/mem/reduction_lut_032.dat" ]\ + [file normalize "${origin_dir}/msu.srcs/mem/reduction_lut_014.dat" ]\ + [file normalize "${origin_dir}/msu.srcs/mem/reduction_lut_027.dat" ]\ + [file normalize "${origin_dir}/msu.srcs/mem/reduction_lut_010.dat" ]\ + [file normalize "${origin_dir}/msu.srcs/mem/reduction_lut_023.dat" ]\ +] +set added_files [add_files -fileset sources_1 $files] + +# Set 'sources_1' fileset file properties for remote files +set file "$origin_dir/../../../primitives/rtl/carry_save_adder.sv" +set file [file normalize $file] +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "SystemVerilog" -objects $file_obj + +set file "$origin_dir/../../../primitives/rtl/carry_save_adder_tree_level.sv" +set file [file normalize $file] +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "SystemVerilog" -objects $file_obj + +set file "$origin_dir/../../../primitives/rtl/compressor_tree_3_to_2.sv" +set file [file normalize $file] +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "SystemVerilog" -objects $file_obj + +set file "$origin_dir/../../../primitives/rtl/full_adder.sv" +set file [file normalize $file] +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "SystemVerilog" -objects $file_obj + +set file "$origin_dir/../../../modular_square/rtl/modular_square_8_cycles.sv" +set file [file normalize $file] +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "SystemVerilog" -objects $file_obj + +set file "$origin_dir/../modular_square_wrapper.sv" +set file [file normalize $file] +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "SystemVerilog" -objects $file_obj + +set file "$origin_dir/../msu.sv" +set file [file normalize $file] +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "SystemVerilog" -objects $file_obj + +set file "$origin_dir/../../../primitives/rtl/multiplier.sv" +set file [file normalize $file] +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "SystemVerilog" -objects $file_obj + +set file "$origin_dir/../../../primitives/rtl/multiply.sv" +set file [file normalize $file] +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "SystemVerilog" -objects $file_obj + +set file "$origin_dir/../sdaccel/vdf_axi_read_master.sv" +set file [file normalize $file] +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "SystemVerilog" -objects $file_obj + +set file "$origin_dir/../sdaccel/vdf_axi_write_master.sv" +set file [file normalize $file] +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "SystemVerilog" -objects $file_obj + +set file "$origin_dir/../sdaccel/vdf_counter.sv" +set file [file normalize $file] +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "SystemVerilog" -objects $file_obj + +set file "$origin_dir/../sdaccel/vdf_kernel.sv" +set file [file normalize $file] +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "SystemVerilog" -objects $file_obj + +set file "$origin_dir/../sdaccel/vdf_wrapper.sv" +set file [file normalize $file] +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "SystemVerilog" -objects $file_obj + + +# Set 'sources_1' fileset file properties for local files +set file "msu.srcs/msuconfig.vh" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "Verilog Header" -objects $file_obj + +set file "mem/reduction_lut.sv" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "SystemVerilog" -objects $file_obj + +set file "mem/reduction_lut_020.dat" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "Data Files" -objects $file_obj + +set file "mem/reduction_lut_012.dat" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "Data Files" -objects $file_obj + +set file "mem/reduction_lut_004.dat" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "Data Files" -objects $file_obj + +set file "mem/reduction_lut_017.dat" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "Data Files" -objects $file_obj + +set file "mem/reduction_lut_009.dat" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "Data Files" -objects $file_obj + +set file "mem/reduction_lut_033.dat" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "Data Files" -objects $file_obj + +set file "mem/reduction_lut_024.dat" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "Data Files" -objects $file_obj + +set file "mem/reduction_lut_026.dat" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "Data Files" -objects $file_obj + +set file "mem/reduction_lut_011.dat" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "Data Files" -objects $file_obj + +set file "mem/reduction_lut_000.dat" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "Data Files" -objects $file_obj + +set file "mem/reduction_lut_029.dat" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "Data Files" -objects $file_obj + +set file "mem/reduction_lut_013.dat" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "Data Files" -objects $file_obj + +set file "mem/reduction_lut_030.dat" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "Data Files" -objects $file_obj + +set file "mem/reduction_lut_007.dat" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "Data Files" -objects $file_obj + +set file "mem/reduction_lut_034.dat" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "Data Files" -objects $file_obj + +set file "mem/reduction_lut_008.dat" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "Data Files" -objects $file_obj + +set file "mem/reduction_lut_016.dat" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "Data Files" -objects $file_obj + +set file "mem/reduction_lut_021.dat" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "Data Files" -objects $file_obj + +set file "mem/reduction_lut_003.dat" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "Data Files" -objects $file_obj + +set file "mem/reduction_lut_025.dat" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "Data Files" -objects $file_obj + +set file "mem/reduction_lut_001.dat" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "Data Files" -objects $file_obj + +set file "mem/reduction_lut_006.dat" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "Data Files" -objects $file_obj + +set file "mem/reduction_lut_031.dat" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "Data Files" -objects $file_obj + +set file "mem/reduction_lut_019.dat" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "Data Files" -objects $file_obj + +set file "mem/reduction_lut_028.dat" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "Data Files" -objects $file_obj + +set file "mem/reduction_lut_022.dat" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "Data Files" -objects $file_obj + +set file "mem/reduction_lut_015.dat" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "Data Files" -objects $file_obj + +set file "mem/reduction_lut_035.dat" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "Data Files" -objects $file_obj + +set file "mem/reduction_lut_018.dat" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "Data Files" -objects $file_obj + +set file "mem/reduction_lut_005.dat" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "Data Files" -objects $file_obj + +set file "mem/reduction_lut_002.dat" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "Data Files" -objects $file_obj + +set file "mem/reduction_lut_032.dat" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "Data Files" -objects $file_obj + +set file "mem/reduction_lut_014.dat" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "Data Files" -objects $file_obj + +set file "mem/reduction_lut_027.dat" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "Data Files" -objects $file_obj + +set file "mem/reduction_lut_010.dat" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "Data Files" -objects $file_obj + +set file "mem/reduction_lut_023.dat" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "Data Files" -objects $file_obj + + +# Set 'sources_1' fileset properties +set obj [get_filesets sources_1] +set_property -name "top" -value "vdf" -objects $obj +set_property -name "top_auto_set" -value "0" -objects $obj + +# Create 'constrs_1' fileset (if not found) +if {[string equal [get_filesets -quiet constrs_1] ""]} { + create_fileset -constrset constrs_1 +} + +# Set 'constrs_1' fileset object +set obj [get_filesets constrs_1] + +# Add/Import constrs file and set constrs file properties +set file "[file normalize "$origin_dir/msu.srcs/constrs_1/new/user.xdc"]" +set file_added [add_files -norecurse -fileset $obj [list $file]] +set file "new/user.xdc" +set file_obj [get_files -of_objects [get_filesets constrs_1] [list "*$file"]] +set_property -name "file_type" -value "XDC" -objects $file_obj + +# Set 'constrs_1' fileset properties +set obj [get_filesets constrs_1] +set_property -name "target_constrs_file" -value "[get_files *new/user.xdc]" -objects $obj +set_property -name "target_ucf" -value "[get_files *new/user.xdc]" -objects $obj + +# Create 'sim_1' fileset (if not found) +if {[string equal [get_filesets -quiet sim_1] ""]} { + create_fileset -simset sim_1 +} + +# Set 'sim_1' fileset object +set obj [get_filesets sim_1] +# Add local files from the original project (-no_copy_sources specified) +set files [list \ + [file normalize "${origin_dir}/msu.srcs/tb.sv" ]\ + [file normalize "${origin_dir}/tb_behav.wcfg" ]\ +] +set added_files [add_files -fileset sim_1 $files] + +# Set 'sim_1' fileset file properties for remote files +# None + +# Set 'sim_1' fileset file properties for local files +set file "msu.srcs/tb.sv" +set file_obj [get_files -of_objects [get_filesets sim_1] [list "*$file"]] +set_property -name "file_type" -value "SystemVerilog" -objects $file_obj + + +# Set 'sim_1' fileset properties +set obj [get_filesets sim_1] +set_property -name "top" -value "tb" -objects $obj +set_property -name "top_auto_set" -value "0" -objects $obj +set_property -name "top_lib" -value "xil_defaultlib" -objects $obj +set_property -name "verilog_define" -value "FASTSIM=1" -objects $obj +set_property -name "xsim.simulate.runtime" -value "100000ns" -objects $obj + +# Set 'utils_1' fileset object +set obj [get_filesets utils_1] +# Empty (no sources present) + +# Set 'utils_1' fileset properties +set obj [get_filesets utils_1] + +# Create 'synth_1' run (if not found) +if {[string equal [get_runs -quiet synth_1] ""]} { + create_run -name synth_1 -part xcvu9p-flga2104-2L-e -flow {Vivado Synthesis 2018} -strategy "Vivado Synthesis Defaults" -report_strategy {No Reports} -constrset constrs_1 +} else { + set_property strategy "Vivado Synthesis Defaults" [get_runs synth_1] + set_property flow "Vivado Synthesis 2018" [get_runs synth_1] +} +set obj [get_runs synth_1] +set_property set_report_strategy_name 1 $obj +set_property report_strategy {Vivado Synthesis Default Reports} $obj +set_property set_report_strategy_name 0 $obj +# Create 'synth_1_synth_report_utilization_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs synth_1] synth_1_synth_report_utilization_0] "" ] } { + create_report_config -report_name synth_1_synth_report_utilization_0 -report_type report_utilization:1.0 -steps synth_design -runs synth_1 +} +set obj [get_report_configs -of_objects [get_runs synth_1] synth_1_synth_report_utilization_0] +if { $obj != "" } { +set_property -name "display_name" -value "synth_1_synth_report_utilization_0" -objects $obj + +} +set obj [get_runs synth_1] +set_property -name "strategy" -value "Vivado Synthesis Defaults" -objects $obj +set_property -name "steps.synth_design.args.more options" -value "-mode out_of_context" -objects $obj + +# set the current synth run +current_run -synthesis [get_runs synth_1] + +# Create 'impl_1' run (if not found) +if {[string equal [get_runs -quiet impl_1] ""]} { + create_run -name impl_1 -part xcvu9p-flga2104-2L-e -flow {Vivado Implementation 2018} -strategy "Vivado Implementation Defaults" -report_strategy {No Reports} -constrset constrs_1 -parent_run synth_1 +} else { + set_property strategy "Vivado Implementation Defaults" [get_runs impl_1] + set_property flow "Vivado Implementation 2018" [get_runs impl_1] +} +set obj [get_runs impl_1] +set_property set_report_strategy_name 1 $obj +set_property report_strategy {Vivado Implementation Default Reports} $obj +set_property set_report_strategy_name 0 $obj +# Create 'impl_1_init_report_timing_summary_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_init_report_timing_summary_0] "" ] } { + create_report_config -report_name impl_1_init_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps init_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_init_report_timing_summary_0] +if { $obj != "" } { +set_property -name "is_enabled" -value "0" -objects $obj +set_property -name "display_name" -value "impl_1_init_report_timing_summary_0" -objects $obj + +} +# Create 'impl_1_opt_report_drc_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_opt_report_drc_0] "" ] } { + create_report_config -report_name impl_1_opt_report_drc_0 -report_type report_drc:1.0 -steps opt_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_opt_report_drc_0] +if { $obj != "" } { +set_property -name "display_name" -value "impl_1_opt_report_drc_0" -objects $obj + +} +# Create 'impl_1_opt_report_timing_summary_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_opt_report_timing_summary_0] "" ] } { + create_report_config -report_name impl_1_opt_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps opt_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_opt_report_timing_summary_0] +if { $obj != "" } { +set_property -name "is_enabled" -value "0" -objects $obj +set_property -name "display_name" -value "impl_1_opt_report_timing_summary_0" -objects $obj + +} +# Create 'impl_1_power_opt_report_timing_summary_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_power_opt_report_timing_summary_0] "" ] } { + create_report_config -report_name impl_1_power_opt_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps power_opt_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_power_opt_report_timing_summary_0] +if { $obj != "" } { +set_property -name "is_enabled" -value "0" -objects $obj +set_property -name "display_name" -value "impl_1_power_opt_report_timing_summary_0" -objects $obj + +} +# Create 'impl_1_place_report_io_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_io_0] "" ] } { + create_report_config -report_name impl_1_place_report_io_0 -report_type report_io:1.0 -steps place_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_io_0] +if { $obj != "" } { +set_property -name "display_name" -value "impl_1_place_report_io_0" -objects $obj + +} +# Create 'impl_1_place_report_utilization_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_utilization_0] "" ] } { + create_report_config -report_name impl_1_place_report_utilization_0 -report_type report_utilization:1.0 -steps place_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_utilization_0] +if { $obj != "" } { +set_property -name "display_name" -value "impl_1_place_report_utilization_0" -objects $obj + +} +# Create 'impl_1_place_report_control_sets_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_control_sets_0] "" ] } { + create_report_config -report_name impl_1_place_report_control_sets_0 -report_type report_control_sets:1.0 -steps place_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_control_sets_0] +if { $obj != "" } { +set_property -name "display_name" -value "impl_1_place_report_control_sets_0" -objects $obj + +} +# Create 'impl_1_place_report_incremental_reuse_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_incremental_reuse_0] "" ] } { + create_report_config -report_name impl_1_place_report_incremental_reuse_0 -report_type report_incremental_reuse:1.0 -steps place_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_incremental_reuse_0] +if { $obj != "" } { +set_property -name "is_enabled" -value "0" -objects $obj +set_property -name "display_name" -value "impl_1_place_report_incremental_reuse_0" -objects $obj + +} +# Create 'impl_1_place_report_incremental_reuse_1' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_incremental_reuse_1] "" ] } { + create_report_config -report_name impl_1_place_report_incremental_reuse_1 -report_type report_incremental_reuse:1.0 -steps place_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_incremental_reuse_1] +if { $obj != "" } { +set_property -name "is_enabled" -value "0" -objects $obj +set_property -name "display_name" -value "impl_1_place_report_incremental_reuse_1" -objects $obj + +} +# Create 'impl_1_place_report_timing_summary_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_timing_summary_0] "" ] } { + create_report_config -report_name impl_1_place_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps place_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_timing_summary_0] +if { $obj != "" } { +set_property -name "is_enabled" -value "0" -objects $obj +set_property -name "display_name" -value "impl_1_place_report_timing_summary_0" -objects $obj + +} +# Create 'impl_1_post_place_power_opt_report_timing_summary_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_post_place_power_opt_report_timing_summary_0] "" ] } { + create_report_config -report_name impl_1_post_place_power_opt_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps post_place_power_opt_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_post_place_power_opt_report_timing_summary_0] +if { $obj != "" } { +set_property -name "is_enabled" -value "0" -objects $obj +set_property -name "display_name" -value "impl_1_post_place_power_opt_report_timing_summary_0" -objects $obj + +} +# Create 'impl_1_phys_opt_report_timing_summary_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_phys_opt_report_timing_summary_0] "" ] } { + create_report_config -report_name impl_1_phys_opt_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps phys_opt_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_phys_opt_report_timing_summary_0] +if { $obj != "" } { +set_property -name "is_enabled" -value "0" -objects $obj +set_property -name "display_name" -value "impl_1_phys_opt_report_timing_summary_0" -objects $obj + +} +# Create 'impl_1_route_report_drc_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_drc_0] "" ] } { + create_report_config -report_name impl_1_route_report_drc_0 -report_type report_drc:1.0 -steps route_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_drc_0] +if { $obj != "" } { +set_property -name "display_name" -value "impl_1_route_report_drc_0" -objects $obj + +} +# Create 'impl_1_route_report_methodology_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_methodology_0] "" ] } { + create_report_config -report_name impl_1_route_report_methodology_0 -report_type report_methodology:1.0 -steps route_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_methodology_0] +if { $obj != "" } { +set_property -name "display_name" -value "impl_1_route_report_methodology_0" -objects $obj + +} +# Create 'impl_1_route_report_power_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_power_0] "" ] } { + create_report_config -report_name impl_1_route_report_power_0 -report_type report_power:1.0 -steps route_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_power_0] +if { $obj != "" } { +set_property -name "display_name" -value "impl_1_route_report_power_0" -objects $obj + +} +# Create 'impl_1_route_report_route_status_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_route_status_0] "" ] } { + create_report_config -report_name impl_1_route_report_route_status_0 -report_type report_route_status:1.0 -steps route_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_route_status_0] +if { $obj != "" } { +set_property -name "display_name" -value "impl_1_route_report_route_status_0" -objects $obj + +} +# Create 'impl_1_route_report_timing_summary_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_timing_summary_0] "" ] } { + create_report_config -report_name impl_1_route_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps route_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_timing_summary_0] +if { $obj != "" } { +set_property -name "display_name" -value "impl_1_route_report_timing_summary_0" -objects $obj + +} +# Create 'impl_1_route_report_incremental_reuse_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_incremental_reuse_0] "" ] } { + create_report_config -report_name impl_1_route_report_incremental_reuse_0 -report_type report_incremental_reuse:1.0 -steps route_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_incremental_reuse_0] +if { $obj != "" } { +set_property -name "display_name" -value "impl_1_route_report_incremental_reuse_0" -objects $obj + +} +# Create 'impl_1_route_report_clock_utilization_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_clock_utilization_0] "" ] } { + create_report_config -report_name impl_1_route_report_clock_utilization_0 -report_type report_clock_utilization:1.0 -steps route_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_clock_utilization_0] +if { $obj != "" } { +set_property -name "display_name" -value "impl_1_route_report_clock_utilization_0" -objects $obj + +} +# Create 'impl_1_route_report_bus_skew_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_bus_skew_0] "" ] } { + create_report_config -report_name impl_1_route_report_bus_skew_0 -report_type report_bus_skew:1.1 -steps route_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_bus_skew_0] +if { $obj != "" } { +set_property -name "display_name" -value "impl_1_route_report_bus_skew_0" -objects $obj + +} +# Create 'impl_1_post_route_phys_opt_report_timing_summary_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_post_route_phys_opt_report_timing_summary_0] "" ] } { + create_report_config -report_name impl_1_post_route_phys_opt_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps post_route_phys_opt_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_post_route_phys_opt_report_timing_summary_0] +if { $obj != "" } { +set_property -name "display_name" -value "impl_1_post_route_phys_opt_report_timing_summary_0" -objects $obj + +} +# Create 'impl_1_post_route_phys_opt_report_bus_skew_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_post_route_phys_opt_report_bus_skew_0] "" ] } { + create_report_config -report_name impl_1_post_route_phys_opt_report_bus_skew_0 -report_type report_bus_skew:1.1 -steps post_route_phys_opt_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_post_route_phys_opt_report_bus_skew_0] +if { $obj != "" } { +set_property -name "display_name" -value "impl_1_post_route_phys_opt_report_bus_skew_0" -objects $obj + +} +set obj [get_runs impl_1] +set_property -name "strategy" -value "Vivado Implementation Defaults" -objects $obj +set_property -name "steps.write_bitstream.args.readback_file" -value "0" -objects $obj +set_property -name "steps.write_bitstream.args.verbose" -value "0" -objects $obj + +# set the current impl run +current_run -implementation [get_runs impl_1] + +puts "INFO: Project created:${_xil_proj_name_}" +set obj [get_dashboards default_dashboard] + +# Create 'drc_1' gadget (if not found) +if {[string equal [get_dashboard_gadgets -of_objects [get_dashboards default_dashboard] [ list "drc_1" ] ] ""]} { +create_dashboard_gadget -name {drc_1} -type drc +} +set obj [get_dashboard_gadgets -of_objects [get_dashboards default_dashboard] [ list "drc_1" ] ] +set_property -name "reports" -value "impl_1#impl_1_route_report_drc_0" -objects $obj + +# Create 'methodology_1' gadget (if not found) +if {[string equal [get_dashboard_gadgets -of_objects [get_dashboards default_dashboard] [ list "methodology_1" ] ] ""]} { +create_dashboard_gadget -name {methodology_1} -type methodology +} +set obj [get_dashboard_gadgets -of_objects [get_dashboards default_dashboard] [ list "methodology_1" ] ] +set_property -name "reports" -value "impl_1#impl_1_route_report_methodology_0" -objects $obj + +# Create 'power_1' gadget (if not found) +if {[string equal [get_dashboard_gadgets -of_objects [get_dashboards default_dashboard] [ list "power_1" ] ] ""]} { +create_dashboard_gadget -name {power_1} -type power +} +set obj [get_dashboard_gadgets -of_objects [get_dashboards default_dashboard] [ list "power_1" ] ] +set_property -name "reports" -value "impl_1#impl_1_route_report_power_0" -objects $obj + +# Create 'timing_1' gadget (if not found) +if {[string equal [get_dashboard_gadgets -of_objects [get_dashboards default_dashboard] [ list "timing_1" ] ] ""]} { +create_dashboard_gadget -name {timing_1} -type timing +} +set obj [get_dashboard_gadgets -of_objects [get_dashboards default_dashboard] [ list "timing_1" ] ] +set_property -name "reports" -value "impl_1#impl_1_route_report_timing_summary_0" -objects $obj + +# Create 'utilization_1' gadget (if not found) +if {[string equal [get_dashboard_gadgets -of_objects [get_dashboards default_dashboard] [ list "utilization_1" ] ] ""]} { +create_dashboard_gadget -name {utilization_1} -type utilization +} +set obj [get_dashboard_gadgets -of_objects [get_dashboards default_dashboard] [ list "utilization_1" ] ] +set_property -name "reports" -value "synth_1#synth_1_synth_report_utilization_0" -objects $obj +set_property -name "run.step" -value "synth_design" -objects $obj +set_property -name "run.type" -value "synthesis" -objects $obj + +# Create 'utilization_2' gadget (if not found) +if {[string equal [get_dashboard_gadgets -of_objects [get_dashboards default_dashboard] [ list "utilization_2" ] ] ""]} { +create_dashboard_gadget -name {utilization_2} -type utilization +} +set obj [get_dashboard_gadgets -of_objects [get_dashboards default_dashboard] [ list "utilization_2" ] ] +set_property -name "reports" -value "impl_1#impl_1_place_report_utilization_0" -objects $obj + +move_dashboard_gadget -name {utilization_1} -row 0 -col 0 +move_dashboard_gadget -name {power_1} -row 1 -col 0 +move_dashboard_gadget -name {drc_1} -row 2 -col 0 +move_dashboard_gadget -name {timing_1} -row 0 -col 1 +move_dashboard_gadget -name {utilization_2} -row 1 -col 1 +move_dashboard_gadget -name {methodology_1} -row 2 -col 1 +# Set current dashboard to 'default_dashboard' +current_dashboard default_dashboard diff --git a/msu/rtl/vivado_ozturk/msu.xpr b/msu/rtl/vivado_ozturk/msu.xpr deleted file mode 100644 index 2670403..0000000 --- a/msu/rtl/vivado_ozturk/msu.xpr +++ /dev/null @@ -1,532 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - default_dashboard - - - - - - diff --git a/msu/rtl/vivado_ozturk/run_vivado.sh b/msu/rtl/vivado_ozturk/run_vivado.sh index 0764e34..6f49daa 100755 --- a/msu/rtl/vivado_ozturk/run_vivado.sh +++ b/msu/rtl/vivado_ozturk/run_vivado.sh @@ -1,6 +1,7 @@ #!/bin/bash # Configuration +# If using 128 bits be sure to change tb.sv as well. export MOD_LEN=1024 MODEL=msu OBJ=../sdaccel/obj_vivado @@ -14,6 +15,12 @@ cd $SCRIPTPATH # (why is there no way to configure the vivado include path?) rm -f ../msuconfig.vh +# Generate a test +# msuconfig.vh from this script will be replaced with the one from +# makefile.sdaccel. +../gen_test.py -s ${MOD_LEN} +rm -f msu.srcs/msuconfig.vh + # Build dependencies mkdir -p ${MODEL}.srcs rm -fr ${OBJ} @@ -21,15 +28,25 @@ mkdir -p ${OBJ} # Delete the any old files first to ensure they are up to date TARGETS="msuconfig.vh mem/reduction_lut_000.dat" -make -C ${OBJ} -f ../Makefile.sdaccel ${TARGETS} +export MODSQR_DIR=../../../../../modular_square +DIRECT_TB=1 make -C ${OBJ} -f ../../multiplier.mk ${TARGETS} # Copy the ROM files into the src directory. cp ${OBJ}/msuconfig.vh ${MODEL}.srcs cp -r ${OBJ}/mem ${MODEL}.srcs rm -fr ${OBJ} +# Generate the Vivado project +if [ ! -d msu ]; then + echo "Generating vivado project" + ./generate.sh +fi + # Update the project directory to the current dir -sed 's@\(Project [^ ]\+ [^ ]\+ Path="\)[^\\"]\+@\1'$SCRIPTPATH/$MODEL.xpr'@' $MODEL.xpr > $MODEL.xpr_new -mv $MODEL.xpr_new $MODEL.xpr +#sed 's@\(Project [^ ]\+ [^ ]\+ Path="\)[^\\"]\+@\1'$SCRIPTPATH/$MODEL.xpr'@' $MODEL.xpr > $MODEL.xpr_new +#mv $MODEL.xpr_new $MODEL.xpr + +cd msu +vivado $MODEL.xpr & + -vivado $MODEL.xpr& diff --git a/msu/rtl/vivado_ozturk/tb_behav.wcfg b/msu/rtl/vivado_ozturk/tb_behav.wcfg new file mode 100644 index 0000000..a06116d --- /dev/null +++ b/msu/rtl/vivado_ozturk/tb_behav.wcfg @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + clk + clk + + + reset + reset + + + start + start + + + valid + valid + + + modulus[1023:0] + modulus[1023:0] + + + sq_in[1023:0] + sq_in[1023:0] + + + sq_out[2111:0] + sq_out[2111:0] + + + t_start[31:0] + t_start[31:0] + + + t_final[31:0] + t_final[31:0] + + diff --git a/msu/rtl/vivado_simple/generate.sh b/msu/rtl/vivado_simple/generate.sh new file mode 100755 index 0000000..e841d22 --- /dev/null +++ b/msu/rtl/vivado_simple/generate.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +vivado -source msu.tcl -mode batch + diff --git a/msu/rtl/vivado_simple/msu.srcs/constrs_1/new/user.xdc b/msu/rtl/vivado_simple/msu.srcs/constrs_1/new/user.xdc new file mode 100644 index 0000000..607ea90 --- /dev/null +++ b/msu/rtl/vivado_simple/msu.srcs/constrs_1/new/user.xdc @@ -0,0 +1,9 @@ + +create_clock -period 10.000 -name ap_clk -waveform {0.000 5.000} [get_ports ap_clk] + +create_pblock sl_exclusion +resize_pblock [get_pblocks sl_exclusion] -add {CLOCKREGION_X4Y0:CLOCKREGION_X5Y9} +set_property EXCLUDE_PLACEMENT 1 [get_pblocks sl_exclusion] +create_pblock SLR2 +add_cells_to_pblock [get_pblocks SLR2] [get_cells -quiet [list inst_wrapper/inst_kernel/msu/modsqr/modsqr]] +resize_pblock [get_pblocks SLR2] -add {CLOCKREGION_X0Y10:CLOCKREGION_X5Y14} diff --git a/msu/rtl/vivado_simple/msu.srcs/tb.sv b/msu/rtl/vivado_simple/msu.srcs/tb.sv new file mode 100644 index 0000000..9d0889d --- /dev/null +++ b/msu/rtl/vivado_simple/msu.srcs/tb.sv @@ -0,0 +1,156 @@ +/******************************************************************************* + Copyright 2019 Supranational LLC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*******************************************************************************/ + +`include "msuconfig.vh" + +module tb(); + localparam integer MOD_LEN = 1024; + //localparam integer MOD_LEN = 128; + + + logic clk; + logic reset; + logic start; + logic valid; + logic [MOD_LEN-1:0] modulus; + logic [MOD_LEN-1:0] sq_in; + logic [MOD_LEN-1:0] sq_out; + logic [MOD_LEN-1:0] sq_out_expected; + logic [MOD_LEN-1:0] sq_out_actual; + + integer t_start; + integer t_final; + integer t_curr; + + integer test_file; + integer i, ret; + integer cycle_count; + integer error_count; + + integer total_cycle_count; + integer total_squarings; + + modular_square_simple + #( + .MOD_LEN(MOD_LEN) + ) + uut( + clk, + reset, + start, + sq_in, + sq_out, + valid + ); + + initial begin + test_file = $fopen("../../../../../test.txt", "r"); + if(test_file == 0) begin + $display("test_file handle was NULL"); + $finish; + end + end + + always begin + #5 clk = ~clk; + end + + initial begin + // Reset the design + clk = 1'b0; + reset = 1'b1; + sq_in = 0; + start = 1'b0; + t_start = 0; + t_curr = 0; + + @(negedge clk); + @(negedge clk); + @(negedge clk); + @(negedge clk); + + reset = 1'b0; + + @(negedge clk); + @(negedge clk); + @(negedge clk); + @(negedge clk); + + // Scan in the modulus and initial value + $fscanf(test_file, "%x\n", sq_in); + @(negedge clk); + + start = 1'b1; + @(negedge clk); + start = 1'b0; + + // Run the squarer and periodically check results + error_count = 0; + total_cycle_count = 0; + total_squarings = 0; + while(1) begin + ret = $fscanf(test_file, "%d, %x\n", t_final, sq_out_expected); + if(ret != 2) begin + break; + end + + // Run to the next checkpoint specified in the test file + cycle_count = 1; + t_start = t_curr; + while(t_curr < t_final) begin + if(valid == 1'b1) begin + t_curr = t_curr + 1; + sq_out_actual = sq_out; + total_squarings = total_squarings + 1; + end + + @(negedge clk); + cycle_count = cycle_count + 1; + total_cycle_count = total_cycle_count + 1; + end + + sq_out_actual = sq_out_actual; + + $display("%5d %0.2f %x", t_final, + real'(cycle_count) / real'(t_final - t_start), + sq_out_actual); + + // Check correctness + if(sq_out_actual !== sq_out_expected) begin + $display("MISTATCH expected %x", sq_out_expected); + $display(" actual %x", sq_out_actual); + error_count = error_count + 1; + break; + end + @(negedge clk); + total_cycle_count = total_cycle_count + 1; + end + $display("Overall %d cycles, %d squarings, %0.2f cyc/sq", + total_cycle_count, total_squarings, + real'(total_cycle_count) / real'(total_squarings)); + if(error_count == 0) begin + $display("SUCCESS!"); + $finish(); + end + @(negedge clk); + @(negedge clk); + @(negedge clk); + @(negedge clk); + $error("FAILURE %d mismatches", error_count); + $finish(); + end +endmodule + diff --git a/msu/rtl/vivado_simple/msu.tcl b/msu/rtl/vivado_simple/msu.tcl new file mode 100644 index 0000000..ee8b25d --- /dev/null +++ b/msu/rtl/vivado_simple/msu.tcl @@ -0,0 +1,570 @@ +#***************************************************************************************** +# Vivado (TM) v2018.3 (64-bit) +# +# msu.tcl: Tcl script for re-creating project 'msu' +# +# Generated by Vivado on Sat Jul 27 21:49:24 EDT 2019 +# IP Build 2404404 on Fri Dec 7 01:43:56 MST 2018 +# +# This file contains the Vivado Tcl commands for re-creating the project to the state* +# when this script was generated. In order to re-create the project, please source this +# file in the Vivado Tcl Shell. +# +# * Note that the runs in the created project will be configured the same way as the +# original project, however they will not be launched automatically. To regenerate the +# run results please launch the synthesis/implementation runs as needed. +# +#***************************************************************************************** +# NOTE: In order to use this script for source control purposes, please make sure that the +# following files are added to the source control system:- +# +# 1. This project restoration tcl script (msu.tcl) that was generated. +# +# 2. The following source(s) files that were local or imported into the original project. +# (Please see the '$orig_proj_dir' and '$origin_dir' variable setting below at the start of the script) +# +# +# +# 3. The following remote source files that were added to the original project:- +# +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev3/msu/rtl/sdaccel/vdf_control_s_axi.v" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev3/msu/rtl/vivado_simple/msu.srcs/msuconfig.vh" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev3/modular_square/rtl/modular_square_simple.sv" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev3/msu/rtl/msu.sv" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev3/msu/rtl/sdaccel/vdf_axi_read_master.sv" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev3/msu/rtl/sdaccel/vdf_axi_write_master.sv" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev3/msu/rtl/sdaccel/vdf_counter.sv" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev3/msu/rtl/sdaccel/vdf_kernel.sv" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev3/msu/rtl/sdaccel/vdf_wrapper.sv" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev3/msu/rtl/sdaccel/vdf.v" +# "/home/snpeffer/src/vdf/fpga_comp/vdf-fpga-dev3/msu/rtl/vivado_simple/msu.srcs/tb.sv" +# +#***************************************************************************************** + +# Set the reference directory for source file relative paths (by default the value is script directory path) +set origin_dir "." + +# Use origin directory path location variable, if specified in the tcl shell +if { [info exists ::origin_dir_loc] } { + set origin_dir $::origin_dir_loc +} + +# Set the project name +set _xil_proj_name_ "msu" + +# Use project name variable, if specified in the tcl shell +if { [info exists ::user_project_name] } { + set _xil_proj_name_ $::user_project_name +} + +variable script_file +set script_file "msu.tcl" + +# Help information for this script +proc print_help {} { + variable script_file + puts "\nDescription:" + puts "Recreate a Vivado project from this script. The created project will be" + puts "functionally equivalent to the original project for which this script was" + puts "generated. The script contains commands for creating a project, filesets," + puts "runs, adding/importing sources and setting properties on various objects.\n" + puts "Syntax:" + puts "$script_file" + puts "$script_file -tclargs \[--origin_dir \]" + puts "$script_file -tclargs \[--project_name \]" + puts "$script_file -tclargs \[--help\]\n" + puts "Usage:" + puts "Name Description" + puts "-------------------------------------------------------------------------" + puts "\[--origin_dir \] Determine source file paths wrt this path. Default" + puts " origin_dir path value is \".\", otherwise, the value" + puts " that was set with the \"-paths_relative_to\" switch" + puts " when this script was generated.\n" + puts "\[--project_name \] Create project with the specified name. Default" + puts " name is the name of the project from where this" + puts " script was generated.\n" + puts "\[--help\] Print help information for this script" + puts "-------------------------------------------------------------------------\n" + exit 0 +} + +if { $::argc > 0 } { + for {set i 0} {$i < $::argc} {incr i} { + set option [string trim [lindex $::argv $i]] + switch -regexp -- $option { + "--origin_dir" { incr i; set origin_dir [lindex $::argv $i] } + "--project_name" { incr i; set _xil_proj_name_ [lindex $::argv $i] } + "--help" { print_help } + default { + if { [regexp {^-} $option] } { + puts "ERROR: Unknown option '$option' specified, please type '$script_file -tclargs --help' for usage info.\n" + return 1 + } + } + } + } +} + +# Set the directory path for the original project from where this script was exported +set orig_proj_dir "[file normalize "$origin_dir/../msu"]" + +# Create project +create_project ${_xil_proj_name_} ./${_xil_proj_name_} -part xcvu9p-flga2104-2L-e + +# Set the directory path for the new project +set proj_dir [get_property directory [current_project]] + +# Set project properties +set obj [current_project] +set_property -name "board_part" -value "xilinx.com:vcu118:part0:2.0" -objects $obj +set_property -name "board_part_repo_paths" -value "/home/snpeffer/src/vdf/artya7/vivado-boards-master/new/board_files" -objects $obj +set_property -name "default_lib" -value "xil_defaultlib" -objects $obj +set_property -name "dsa.accelerator_binary_content" -value "bitstream" -objects $obj +set_property -name "dsa.accelerator_binary_format" -value "xclbin2" -objects $obj +set_property -name "dsa.board_id" -value "vcu118" -objects $obj +set_property -name "dsa.description" -value "Vivado generated DSA" -objects $obj +set_property -name "dsa.dr_bd_base_address" -value "0" -objects $obj +set_property -name "dsa.emu_dir" -value "emu" -objects $obj +set_property -name "dsa.flash_interface_type" -value "bpix16" -objects $obj +set_property -name "dsa.flash_offset_address" -value "0" -objects $obj +set_property -name "dsa.flash_size" -value "1024" -objects $obj +set_property -name "dsa.host_architecture" -value "x86_64" -objects $obj +set_property -name "dsa.host_interface" -value "pcie" -objects $obj +set_property -name "dsa.num_compute_units" -value "60" -objects $obj +set_property -name "dsa.platform_state" -value "pre_synth" -objects $obj +set_property -name "dsa.vendor" -value "xilinx" -objects $obj +set_property -name "dsa.version" -value "0.0" -objects $obj +set_property -name "enable_vhdl_2008" -value "1" -objects $obj +set_property -name "ip_cache_permissions" -value "read write" -objects $obj +set_property -name "ip_output_repo" -value "$proj_dir/${_xil_proj_name_}.cache/ip" -objects $obj +set_property -name "mem.enable_memory_map_generation" -value "1" -objects $obj +set_property -name "sim.central_dir" -value "$proj_dir/${_xil_proj_name_}.ip_user_files" -objects $obj +set_property -name "sim.ip.auto_export_scripts" -value "1" -objects $obj +set_property -name "simulator_language" -value "Mixed" -objects $obj +set_property -name "webtalk.xsim_launch_sim" -value "45" -objects $obj + +# Create 'sources_1' fileset (if not found) +if {[string equal [get_filesets -quiet sources_1] ""]} { + create_fileset -srcset sources_1 +} + +# Set 'sources_1' fileset object +set obj [get_filesets sources_1] +set files [list \ + [file normalize "${origin_dir}/../sdaccel/vdf_control_s_axi.v"] \ + [file normalize "${origin_dir}/msu.srcs/msuconfig.vh"] \ + [file normalize "${origin_dir}/../../../modular_square/rtl/modular_square_simple.sv"] \ + [file normalize "${origin_dir}/../msu.sv"] \ + [file normalize "${origin_dir}/../sdaccel/vdf_axi_read_master.sv"] \ + [file normalize "${origin_dir}/../sdaccel/vdf_axi_write_master.sv"] \ + [file normalize "${origin_dir}/../sdaccel/vdf_counter.sv"] \ + [file normalize "${origin_dir}/../sdaccel/vdf_kernel.sv"] \ + [file normalize "${origin_dir}/../sdaccel/vdf_wrapper.sv"] \ + [file normalize "${origin_dir}/../sdaccel/vdf.v"] \ +] +add_files -norecurse -fileset $obj $files + +# Set 'sources_1' fileset file properties for remote files +set file "msu.srcs/msuconfig.vh" +set file [file normalize $file] +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "Verilog Header" -objects $file_obj + +set file "$origin_dir/../../../modular_square/rtl/modular_square_simple.sv" +set file [file normalize $file] +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "SystemVerilog" -objects $file_obj + +set file "$origin_dir/../msu.sv" +set file [file normalize $file] +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "SystemVerilog" -objects $file_obj + +set file "$origin_dir/../sdaccel/vdf_axi_read_master.sv" +set file [file normalize $file] +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "SystemVerilog" -objects $file_obj + +set file "$origin_dir/../sdaccel/vdf_axi_write_master.sv" +set file [file normalize $file] +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "SystemVerilog" -objects $file_obj + +set file "$origin_dir/../sdaccel/vdf_counter.sv" +set file [file normalize $file] +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "SystemVerilog" -objects $file_obj + +set file "$origin_dir/../sdaccel/vdf_kernel.sv" +set file [file normalize $file] +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "SystemVerilog" -objects $file_obj + +set file "$origin_dir/../sdaccel/vdf_wrapper.sv" +set file [file normalize $file] +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "SystemVerilog" -objects $file_obj + + +# Set 'sources_1' fileset file properties for local files +# None + +# Set 'sources_1' fileset properties +set obj [get_filesets sources_1] +set_property -name "top" -value "vdf" -objects $obj + +# Create 'constrs_1' fileset (if not found) +if {[string equal [get_filesets -quiet constrs_1] ""]} { + create_fileset -constrset constrs_1 +} + +# Set 'constrs_1' fileset object +set obj [get_filesets constrs_1] + +# Empty (no sources present) + +# Set 'constrs_1' fileset properties +set obj [get_filesets constrs_1] + +# Create 'sim_1' fileset (if not found) +if {[string equal [get_filesets -quiet sim_1] ""]} { + create_fileset -simset sim_1 +} + +# Set 'sim_1' fileset object +set obj [get_filesets sim_1] +set files [list \ + [file normalize "${origin_dir}/msu.srcs/tb.sv"] \ +] +add_files -norecurse -fileset $obj $files + +# Set 'sim_1' fileset file properties for remote files +set file "msu.srcs/tb.sv" +set file [file normalize $file] +set file_obj [get_files -of_objects [get_filesets sim_1] [list "*$file"]] +set_property -name "file_type" -value "SystemVerilog" -objects $file_obj + + +# Set 'sim_1' fileset file properties for local files +# None + +# Set 'sim_1' fileset properties +set obj [get_filesets sim_1] +set_property -name "top" -value "tb" -objects $obj +set_property -name "top_auto_set" -value "0" -objects $obj +set_property -name "top_lib" -value "xil_defaultlib" -objects $obj +set_property -name "xsim.simulate.runtime" -value "101000ns" -objects $obj + +# Set 'utils_1' fileset object +set obj [get_filesets utils_1] +# Empty (no sources present) + +# Set 'utils_1' fileset properties +set obj [get_filesets utils_1] + +# Create 'synth_1' run (if not found) +if {[string equal [get_runs -quiet synth_1] ""]} { + create_run -name synth_1 -part xcvu9p-flga2104-2L-e -flow {Vivado Synthesis 2018} -strategy "Vivado Synthesis Defaults" -report_strategy {No Reports} -constrset constrs_1 +} else { + set_property strategy "Vivado Synthesis Defaults" [get_runs synth_1] + set_property flow "Vivado Synthesis 2018" [get_runs synth_1] +} +set obj [get_runs synth_1] +set_property set_report_strategy_name 1 $obj +set_property report_strategy {Vivado Synthesis Default Reports} $obj +set_property set_report_strategy_name 0 $obj +# Create 'synth_1_synth_report_utilization_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs synth_1] synth_1_synth_report_utilization_0] "" ] } { + create_report_config -report_name synth_1_synth_report_utilization_0 -report_type report_utilization:1.0 -steps synth_design -runs synth_1 +} +set obj [get_report_configs -of_objects [get_runs synth_1] synth_1_synth_report_utilization_0] +if { $obj != "" } { +set_property -name "display_name" -value "synth_1_synth_report_utilization_0" -objects $obj + +} +set obj [get_runs synth_1] +set_property -name "strategy" -value "Vivado Synthesis Defaults" -objects $obj + +# set the current synth run +current_run -synthesis [get_runs synth_1] + +# Create 'impl_1' run (if not found) +if {[string equal [get_runs -quiet impl_1] ""]} { + create_run -name impl_1 -part xcvu9p-flga2104-2L-e -flow {Vivado Implementation 2018} -strategy "Vivado Implementation Defaults" -report_strategy {No Reports} -constrset constrs_1 -parent_run synth_1 +} else { + set_property strategy "Vivado Implementation Defaults" [get_runs impl_1] + set_property flow "Vivado Implementation 2018" [get_runs impl_1] +} +set obj [get_runs impl_1] +set_property set_report_strategy_name 1 $obj +set_property report_strategy {Vivado Implementation Default Reports} $obj +set_property set_report_strategy_name 0 $obj +# Create 'impl_1_init_report_timing_summary_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_init_report_timing_summary_0] "" ] } { + create_report_config -report_name impl_1_init_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps init_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_init_report_timing_summary_0] +if { $obj != "" } { +set_property -name "is_enabled" -value "0" -objects $obj +set_property -name "display_name" -value "impl_1_init_report_timing_summary_0" -objects $obj + +} +# Create 'impl_1_opt_report_drc_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_opt_report_drc_0] "" ] } { + create_report_config -report_name impl_1_opt_report_drc_0 -report_type report_drc:1.0 -steps opt_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_opt_report_drc_0] +if { $obj != "" } { +set_property -name "display_name" -value "impl_1_opt_report_drc_0" -objects $obj + +} +# Create 'impl_1_opt_report_timing_summary_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_opt_report_timing_summary_0] "" ] } { + create_report_config -report_name impl_1_opt_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps opt_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_opt_report_timing_summary_0] +if { $obj != "" } { +set_property -name "is_enabled" -value "0" -objects $obj +set_property -name "display_name" -value "impl_1_opt_report_timing_summary_0" -objects $obj + +} +# Create 'impl_1_power_opt_report_timing_summary_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_power_opt_report_timing_summary_0] "" ] } { + create_report_config -report_name impl_1_power_opt_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps power_opt_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_power_opt_report_timing_summary_0] +if { $obj != "" } { +set_property -name "is_enabled" -value "0" -objects $obj +set_property -name "display_name" -value "impl_1_power_opt_report_timing_summary_0" -objects $obj + +} +# Create 'impl_1_place_report_io_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_io_0] "" ] } { + create_report_config -report_name impl_1_place_report_io_0 -report_type report_io:1.0 -steps place_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_io_0] +if { $obj != "" } { +set_property -name "display_name" -value "impl_1_place_report_io_0" -objects $obj + +} +# Create 'impl_1_place_report_utilization_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_utilization_0] "" ] } { + create_report_config -report_name impl_1_place_report_utilization_0 -report_type report_utilization:1.0 -steps place_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_utilization_0] +if { $obj != "" } { +set_property -name "display_name" -value "impl_1_place_report_utilization_0" -objects $obj + +} +# Create 'impl_1_place_report_control_sets_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_control_sets_0] "" ] } { + create_report_config -report_name impl_1_place_report_control_sets_0 -report_type report_control_sets:1.0 -steps place_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_control_sets_0] +if { $obj != "" } { +set_property -name "display_name" -value "impl_1_place_report_control_sets_0" -objects $obj + +} +# Create 'impl_1_place_report_incremental_reuse_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_incremental_reuse_0] "" ] } { + create_report_config -report_name impl_1_place_report_incremental_reuse_0 -report_type report_incremental_reuse:1.0 -steps place_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_incremental_reuse_0] +if { $obj != "" } { +set_property -name "is_enabled" -value "0" -objects $obj +set_property -name "display_name" -value "impl_1_place_report_incremental_reuse_0" -objects $obj + +} +# Create 'impl_1_place_report_incremental_reuse_1' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_incremental_reuse_1] "" ] } { + create_report_config -report_name impl_1_place_report_incremental_reuse_1 -report_type report_incremental_reuse:1.0 -steps place_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_incremental_reuse_1] +if { $obj != "" } { +set_property -name "is_enabled" -value "0" -objects $obj +set_property -name "display_name" -value "impl_1_place_report_incremental_reuse_1" -objects $obj + +} +# Create 'impl_1_place_report_timing_summary_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_timing_summary_0] "" ] } { + create_report_config -report_name impl_1_place_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps place_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_timing_summary_0] +if { $obj != "" } { +set_property -name "is_enabled" -value "0" -objects $obj +set_property -name "display_name" -value "impl_1_place_report_timing_summary_0" -objects $obj + +} +# Create 'impl_1_post_place_power_opt_report_timing_summary_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_post_place_power_opt_report_timing_summary_0] "" ] } { + create_report_config -report_name impl_1_post_place_power_opt_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps post_place_power_opt_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_post_place_power_opt_report_timing_summary_0] +if { $obj != "" } { +set_property -name "is_enabled" -value "0" -objects $obj +set_property -name "display_name" -value "impl_1_post_place_power_opt_report_timing_summary_0" -objects $obj + +} +# Create 'impl_1_phys_opt_report_timing_summary_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_phys_opt_report_timing_summary_0] "" ] } { + create_report_config -report_name impl_1_phys_opt_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps phys_opt_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_phys_opt_report_timing_summary_0] +if { $obj != "" } { +set_property -name "is_enabled" -value "0" -objects $obj +set_property -name "display_name" -value "impl_1_phys_opt_report_timing_summary_0" -objects $obj + +} +# Create 'impl_1_route_report_drc_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_drc_0] "" ] } { + create_report_config -report_name impl_1_route_report_drc_0 -report_type report_drc:1.0 -steps route_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_drc_0] +if { $obj != "" } { +set_property -name "display_name" -value "impl_1_route_report_drc_0" -objects $obj + +} +# Create 'impl_1_route_report_methodology_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_methodology_0] "" ] } { + create_report_config -report_name impl_1_route_report_methodology_0 -report_type report_methodology:1.0 -steps route_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_methodology_0] +if { $obj != "" } { +set_property -name "display_name" -value "impl_1_route_report_methodology_0" -objects $obj + +} +# Create 'impl_1_route_report_power_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_power_0] "" ] } { + create_report_config -report_name impl_1_route_report_power_0 -report_type report_power:1.0 -steps route_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_power_0] +if { $obj != "" } { +set_property -name "display_name" -value "impl_1_route_report_power_0" -objects $obj + +} +# Create 'impl_1_route_report_route_status_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_route_status_0] "" ] } { + create_report_config -report_name impl_1_route_report_route_status_0 -report_type report_route_status:1.0 -steps route_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_route_status_0] +if { $obj != "" } { +set_property -name "display_name" -value "impl_1_route_report_route_status_0" -objects $obj + +} +# Create 'impl_1_route_report_timing_summary_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_timing_summary_0] "" ] } { + create_report_config -report_name impl_1_route_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps route_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_timing_summary_0] +if { $obj != "" } { +set_property -name "display_name" -value "impl_1_route_report_timing_summary_0" -objects $obj + +} +# Create 'impl_1_route_report_incremental_reuse_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_incremental_reuse_0] "" ] } { + create_report_config -report_name impl_1_route_report_incremental_reuse_0 -report_type report_incremental_reuse:1.0 -steps route_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_incremental_reuse_0] +if { $obj != "" } { +set_property -name "display_name" -value "impl_1_route_report_incremental_reuse_0" -objects $obj + +} +# Create 'impl_1_route_report_clock_utilization_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_clock_utilization_0] "" ] } { + create_report_config -report_name impl_1_route_report_clock_utilization_0 -report_type report_clock_utilization:1.0 -steps route_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_clock_utilization_0] +if { $obj != "" } { +set_property -name "display_name" -value "impl_1_route_report_clock_utilization_0" -objects $obj + +} +# Create 'impl_1_route_report_bus_skew_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_bus_skew_0] "" ] } { + create_report_config -report_name impl_1_route_report_bus_skew_0 -report_type report_bus_skew:1.1 -steps route_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_bus_skew_0] +if { $obj != "" } { +set_property -name "display_name" -value "impl_1_route_report_bus_skew_0" -objects $obj + +} +# Create 'impl_1_post_route_phys_opt_report_timing_summary_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_post_route_phys_opt_report_timing_summary_0] "" ] } { + create_report_config -report_name impl_1_post_route_phys_opt_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps post_route_phys_opt_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_post_route_phys_opt_report_timing_summary_0] +if { $obj != "" } { +set_property -name "display_name" -value "impl_1_post_route_phys_opt_report_timing_summary_0" -objects $obj + +} +# Create 'impl_1_post_route_phys_opt_report_bus_skew_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_post_route_phys_opt_report_bus_skew_0] "" ] } { + create_report_config -report_name impl_1_post_route_phys_opt_report_bus_skew_0 -report_type report_bus_skew:1.1 -steps post_route_phys_opt_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_post_route_phys_opt_report_bus_skew_0] +if { $obj != "" } { +set_property -name "display_name" -value "impl_1_post_route_phys_opt_report_bus_skew_0" -objects $obj + +} +set obj [get_runs impl_1] +set_property -name "strategy" -value "Vivado Implementation Defaults" -objects $obj +set_property -name "steps.write_bitstream.args.readback_file" -value "0" -objects $obj +set_property -name "steps.write_bitstream.args.verbose" -value "0" -objects $obj + +# set the current impl run +current_run -implementation [get_runs impl_1] + +puts "INFO: Project created:${_xil_proj_name_}" +set obj [get_dashboards default_dashboard] + +# Create 'drc_1' gadget (if not found) +if {[string equal [get_dashboard_gadgets -of_objects [get_dashboards default_dashboard] [ list "drc_1" ] ] ""]} { +create_dashboard_gadget -name {drc_1} -type drc +} +set obj [get_dashboard_gadgets -of_objects [get_dashboards default_dashboard] [ list "drc_1" ] ] +set_property -name "reports" -value "impl_1#impl_1_route_report_drc_0" -objects $obj + +# Create 'methodology_1' gadget (if not found) +if {[string equal [get_dashboard_gadgets -of_objects [get_dashboards default_dashboard] [ list "methodology_1" ] ] ""]} { +create_dashboard_gadget -name {methodology_1} -type methodology +} +set obj [get_dashboard_gadgets -of_objects [get_dashboards default_dashboard] [ list "methodology_1" ] ] +set_property -name "reports" -value "impl_1#impl_1_route_report_methodology_0" -objects $obj + +# Create 'power_1' gadget (if not found) +if {[string equal [get_dashboard_gadgets -of_objects [get_dashboards default_dashboard] [ list "power_1" ] ] ""]} { +create_dashboard_gadget -name {power_1} -type power +} +set obj [get_dashboard_gadgets -of_objects [get_dashboards default_dashboard] [ list "power_1" ] ] +set_property -name "reports" -value "impl_1#impl_1_route_report_power_0" -objects $obj + +# Create 'timing_1' gadget (if not found) +if {[string equal [get_dashboard_gadgets -of_objects [get_dashboards default_dashboard] [ list "timing_1" ] ] ""]} { +create_dashboard_gadget -name {timing_1} -type timing +} +set obj [get_dashboard_gadgets -of_objects [get_dashboards default_dashboard] [ list "timing_1" ] ] +set_property -name "reports" -value "impl_1#impl_1_route_report_timing_summary_0" -objects $obj + +# Create 'utilization_1' gadget (if not found) +if {[string equal [get_dashboard_gadgets -of_objects [get_dashboards default_dashboard] [ list "utilization_1" ] ] ""]} { +create_dashboard_gadget -name {utilization_1} -type utilization +} +set obj [get_dashboard_gadgets -of_objects [get_dashboards default_dashboard] [ list "utilization_1" ] ] +set_property -name "reports" -value "synth_1#synth_1_synth_report_utilization_0" -objects $obj +set_property -name "run.step" -value "synth_design" -objects $obj +set_property -name "run.type" -value "synthesis" -objects $obj + +# Create 'utilization_2' gadget (if not found) +if {[string equal [get_dashboard_gadgets -of_objects [get_dashboards default_dashboard] [ list "utilization_2" ] ] ""]} { +create_dashboard_gadget -name {utilization_2} -type utilization +} +set obj [get_dashboard_gadgets -of_objects [get_dashboards default_dashboard] [ list "utilization_2" ] ] +set_property -name "reports" -value "impl_1#impl_1_place_report_utilization_0" -objects $obj + +move_dashboard_gadget -name {utilization_1} -row 0 -col 0 +move_dashboard_gadget -name {power_1} -row 1 -col 0 +move_dashboard_gadget -name {drc_1} -row 2 -col 0 +move_dashboard_gadget -name {timing_1} -row 0 -col 1 +move_dashboard_gadget -name {utilization_2} -row 1 -col 1 +move_dashboard_gadget -name {methodology_1} -row 2 -col 1 +# Set current dashboard to 'default_dashboard' +current_dashboard default_dashboard diff --git a/msu/rtl/vivado_simple/msu.xpr b/msu/rtl/vivado_simple/msu.xpr deleted file mode 100644 index af4df9a..0000000 --- a/msu/rtl/vivado_simple/msu.xpr +++ /dev/null @@ -1,260 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - default_dashboard - - - - - - diff --git a/msu/rtl/vivado_simple/run_vivado.sh b/msu/rtl/vivado_simple/run_vivado.sh index 0cb88b5..65f275f 100755 --- a/msu/rtl/vivado_simple/run_vivado.sh +++ b/msu/rtl/vivado_simple/run_vivado.sh @@ -1,10 +1,9 @@ #!/bin/bash # Configuration -export MOD_LEN=128 +export MOD_LEN=1024 export SIMPLE_SQ=1 MODEL=msu -OBJ=../sdaccel/obj_vivado # Set current directory to the location of this script SCRIPT=$(dirname "$0") @@ -15,21 +14,18 @@ cd $SCRIPTPATH # (why is there no way to configure the vivado include path?) rm -f ../msuconfig.vh -# Build dependencies -mkdir -p ${MODEL}.srcs -rm -fr ${OBJ} -mkdir -p ${OBJ} +# Generate a test +../gen_test.py -c -# Delete the any old files first to ensure they are up to date -TARGETS="msuconfig.vh" -make -C ${OBJ} -f ../Makefile.sdaccel ${TARGETS} - -# Copy the ROM files into the src directory. -cp ${OBJ}/msuconfig.vh ${MODEL}.srcs -rm -fr ${OBJ} +# Generate the Vivado project +if [ ! -d msu ]; then + echo "Generating vivado project" + ./generate.sh +fi # Update the project directory to the current dir -sed 's@\(Project [^ ]\+ [^ ]\+ Path="\)[^\\"]\+@\1'$SCRIPTPATH/$MODEL.xpr'@' $MODEL.xpr > $MODEL.xpr_new -mv $MODEL.xpr_new $MODEL.xpr +#sed 's@\(Project [^ ]\+ [^ ]\+ Path="\)[^\\"]\+@\1'$SCRIPTPATH/$MODEL.xpr'@' $MODEL.xpr > $MODEL.xpr_new +#mv $MODEL.xpr_new $MODEL.xpr -vivado $MODEL.xpr& +cd msu +vivado $MODEL.xpr & diff --git a/msu/rtl/vivado_simple/tb_behav.wcfg b/msu/rtl/vivado_simple/tb_behav.wcfg new file mode 100644 index 0000000..4ffd39b --- /dev/null +++ b/msu/rtl/vivado_simple/tb_behav.wcfg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + clk + clk + + + reset + reset + + + start + start + + + sq_in[1023:0] + sq_in[1023:0] + + + sq_out[1023:0] + sq_out[1023:0] + + + valid + valid + + diff --git a/msu/sw/MSUVerilatorDirect.cpp b/msu/sw/MSUVerilatorDirect.cpp index b3ed294..85586d5 100644 --- a/msu/sw/MSUVerilatorDirect.cpp +++ b/msu/sw/MSUVerilatorDirect.cpp @@ -130,9 +130,13 @@ void MSUVerilator::compute_job(uint64_t t_start, clock_cycle(); } pet(); - - clock_cycle(); + t_cur++; + if(t_cur == t_final) { + break; + } + + clock_cycle(); } bn_from_buffer(msu_out, tb->sq_out, squarer->msu_words_out());