From a44b043a2ae3c20bd0d0b787ab86010bc5d3ffab Mon Sep 17 00:00:00 2001 From: dpgrubb13 Date: Fri, 30 Aug 2019 18:57:11 -0700 Subject: [PATCH 01/39] additions to example-vlsi for asap7 demo --- vlsi/example-vlsi | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/vlsi/example-vlsi b/vlsi/example-vlsi index 3f65d9a5..5d43f8c5 100755 --- a/vlsi/example-vlsi +++ b/vlsi/example-vlsi @@ -8,12 +8,41 @@ from typing import Dict, Callable, Optional, List def example_place_tap_cells(x: hammer_vlsi.HammerTool) -> bool: x.append(''' # TODO +# Place custom TCL here +''') + return True + +def example_add_fillers(x: hammer_vlsi.HammerTool) -> bool: + x.append(''' +# TODO +# Place custom TCL here +''') + return True + +def example_tool_settings(x: hammer_vlsi.HammerTool) -> bool: + x.append(''' +# TODO +# Place custom TCL here ''') return True class ExampleDriver(CLIDriver): def get_extra_par_hooks(self) -> List[HammerToolHookAction]: - return [hammer_vlsi.HammerTool.make_replacement_hook("place_tap_cells", example_place_tap_cells)] + extra_hooks = [ + + # Default set of steps can be found in the CAD tool plugin's __init__.py + + # make_pre_insertion_hook will execute the custom hook before the specified step + hammer_vlsi.HammerTool.make_pre_insertion_hook("route_design", example_add_fillers), # SYNTAX: make_pre_insertion_hook("EXISTING_STEP", INSERTED_HOOK) + # make_post_insertion_hook will execute the custom hook after the specified step + hammer_vlsi.HammerTool.make_post_insertion_hook("init_design", example_tool_settings), + # make_replacement_hook will replace the specified step with a custom hook + hammer_vlsi.HammerTool.make_replacement_hook("place_tap_cells", example_place_tap_cells), + # make_removal_hook will remove the specified step from the flow + hammer_vlsi.HammerTool.make_removal_hook("place_bumps") + # The target step in any of the above calls may be a default step or another one of your custom hooks + ] + return extra_hooks if __name__ == '__main__': ExampleDriver().main() From 859492c2a2d5be518da552b08ddd23c0c32473c2 Mon Sep 17 00:00:00 2001 From: dpgrubb13 Date: Sat, 31 Aug 2019 00:40:25 -0700 Subject: [PATCH 02/39] added starter example.yml --- vlsi/example.yml | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 vlsi/example.yml diff --git a/vlsi/example.yml b/vlsi/example.yml new file mode 100644 index 00000000..790479c9 --- /dev/null +++ b/vlsi/example.yml @@ -0,0 +1,35 @@ +# Technology Setup +# Technology used is ASAP7 +vlsi.core.technology: asap7 +vlsi.core.node: 7 +technology.asap7.tarball_dir: "SPECIFY DIR WITH ASAP7 TARBALL" +technology.asap7.install_dir: "SPECIFY EXTRACTED DIR HERE IF NOT USING TARBALL" + +vlsi.core.max_threads: 12 + +# General Hammer Inputs + +vlsi.inputs.supplies.VDD: "0.7 V" + +# Hammer will auto-generate a CPF for simple power designs; see hammer/src/hammer-vlsi/defaults.yml for more info +vlsi.inputs.power_spec_mode: "auto" + +# Specify the setup and hold corners for ASAP7 +vlsi.inputs.mmmc_corners: [ + {name: "PVT_0P63V_100C", type: "setup", voltage: "0.63 V", temp: "100 C"}, + {name: "PVT_0P77V_0C", type: "hold", voltage: "0.77 V", temp: "0 C"} +] + +# Specify clock signals +vlsi.inputs.clocks: [ + {name: "clock", period: "10ns", uncertainty: "0.1ns"} +] + +# Generate Make include to aid in flow +vlsi.core.build_system: make + +# Power Straps +par.power_straps_mode: generate + +# Placement Constraints +#vlsi.inputs.placement_constraints: From 6179a91a294e832f035e8e125eb450ecb04766e7 Mon Sep 17 00:00:00 2001 From: Harrison Liew Date: Sat, 31 Aug 2019 20:04:35 -0700 Subject: [PATCH 03/39] some plumbing but still need to remove sram generator target for asap7 --- .gitmodules | 12 ++++++-- scripts/init-vlsi.sh | 10 ++++-- vlsi/Makefile | 8 ++--- vlsi/README.md | 60 +++++++++++++++++++++++++++++++++--- vlsi/bwrc-env.yml | 7 +++++ vlsi/example.yml | 54 +++++++++++++++++++++++++++++++- vlsi/hammer | 2 +- vlsi/hammer-cad-plugins | 1 - vlsi/hammer-cadence-plugins | 1 + vlsi/hammer-mentor-plugins | 1 + vlsi/hammer-synopsys-plugins | 1 + 11 files changed, 140 insertions(+), 17 deletions(-) create mode 100644 vlsi/bwrc-env.yml delete mode 160000 vlsi/hammer-cad-plugins create mode 160000 vlsi/hammer-cadence-plugins create mode 160000 vlsi/hammer-mentor-plugins create mode 160000 vlsi/hammer-synopsys-plugins diff --git a/.gitmodules b/.gitmodules index 4bbfaa97..35addf76 100644 --- a/.gitmodules +++ b/.gitmodules @@ -43,9 +43,6 @@ [submodule "vlsi/hammer"] path = vlsi/hammer url = https://github.com/ucb-bar/hammer.git -[submodule "vlsi/hammer-cad-plugins"] - path = vlsi/hammer-cad-plugins - url = https://github.com/ucb-bar/hammer-cad-plugins.git [submodule "tools/dsptools"] path = tools/dsptools url = https://github.com/ucb-bar/dsptools.git @@ -61,3 +58,12 @@ [submodule "tools/firrtl-interpreter"] path = tools/firrtl-interpreter url = https://github.com/freechipsproject/firrtl-interpreter.git +[submodule "vlsi/hammer-cadence-plugins"] + path = vlsi/hammer-cadence-plugins + url = git@github.com:ucb-bar/hammer-cadence-plugins.git +[submodule "vlsi/hammer-synopsys-plugins"] + path = vlsi/hammer-synopsys-plugins + url = git@github.com:ucb-bar/hammer-synopsys-plugins.git +[submodule "vlsi/hammer-mentor-plugins"] + path = vlsi/hammer-mentor-plugins + url = git@github.com:ucb-bar/hammer-mentor-plugins.git diff --git a/scripts/init-vlsi.sh b/scripts/init-vlsi.sh index 89f9ac56..aaf015ca 100755 --- a/scripts/init-vlsi.sh +++ b/scripts/init-vlsi.sh @@ -1,11 +1,15 @@ #!/usr/bin/env bash -# exit script if any command fails +# exit script if any command fails set -e set -o pipefail # Initialize HAMMER and CAD-plugins git submodule update --init --recursive vlsi/hammer -git submodule update --init --recursive vlsi/hammer-cad-plugins +git submodule update --init --recursive vlsi/hammer-cadence-plugins +git submodule update --init --recursive vlsi/hammer-synopsys-plugins +git submodule update --init --recursive vlsi/hammer-mentor-plugins # Initialize HAMMER tech plugin -git submodule update --init --recursive vlsi/hammer-"$1"-plugin +if [[ $1 != *asap7* ]] && [[ $1 != *saed32* ]]; then + git submodule update --init --recursive vlsi/hammer-$1-plugin +fi diff --git a/vlsi/Makefile b/vlsi/Makefile index 519d1448..6fcedd62 100644 --- a/vlsi/Makefile +++ b/vlsi/Makefile @@ -18,15 +18,15 @@ include $(base_dir)/variables.mk # vlsi types and rules ######################################################################################### sim_name ?= vcs # needed for GenerateSimFiles, but is unused -tech_name ?= -tech_dir ?= $(vlsi_dir)/hammer-$(tech_name)-plugin/$(tech_name) +tech_name ?= asap7 +tech_dir ?= $(if $(filter $(tech_name), asap7 saed32), $(vlsi_dir)/hammer/src/hammer-vlsi/technology/$(tech_name), $(vlsi_dir)/hammer-$(tech_name)-plugin/$(tech_name)) SMEMS_COMP ?= $(tech_dir)/sram-compiler.json -SMEMS_CACHE ?= $(tech_dir)/sram-cache.json +cMEMS_CACHE ?= $(tech_dir)/sram-cache.json SMEMS_HAMMER ?= $(build_dir)/$(long_name).mems.hammer.json MACROCOMPILER_MODE ?= -l $(SMEMS_CACHE) -hir $(SMEMS_HAMMER) OBJ_DIR ?= $(vlsi_dir)/build ENV_YML ?= $(vlsi_dir)/bwrc-env.yml -INPUT_CONFS ?= example.yml $(dir $(tech_dir))/bwrc.yml +INPUT_CONFS ?= example.yml HAMMER_EXEC ?= ./example-vlsi ######################################################################################### diff --git a/vlsi/README.md b/vlsi/README.md index aa07dd0f..0ee8978d 100644 --- a/vlsi/README.md +++ b/vlsi/README.md @@ -2,8 +2,60 @@ This is the starting point for a vlsi flow from this repository. This flow will not work without the necessary CAD and technology plugins for HAMMER. -If you are a UCB-affiliate, you may be able to acquire access to the tech-plugins. +If you are a UCB-affiliate, you may be able to acquire access to the tool & tech plugins. -# Initial Setup Instructions (For All technologies) -Run the `init-vlsi.sh` script to pull correct versions of hammer, hammer-cad-plugins, and the hammer-tech-plugins -```scripts/init-vlsi.sh TECH_NAME``` \ No newline at end of file +# Initial Setup Instructions (For all technologies) +Run the `init-vlsi.sh` script to pull correct versions of hammer, hammer-TOOL\_VENDOR-plugins, and the hammer-TECH\_NAME-plugins. Note the included technology 'asap7' is already included and will not submodule a tech plugin. +```shell +scripts/init-vlsi.sh TECH_NAME +``` + +An example of tool environment configuration for BWRC affiliates is given in `bwrc-env.yml`. Replace as necessary for your environment. + +Finally, set up all prerequisites for the build system: +```shell +make buildfile +``` + +# Example design +In this example, you will be running a SHA-3 accelerator through the VLSI flow. It is assumed that you have already run through the flow to elaborate the Chisel into Verilog. + +HAMMER's configuration is driven by a JSON/YAML format. For HAMMER, JSON and YAML files are equivalent - you can use either one since HAMMER will convert them to the same representation for itself. + +We start by pulling the HAMMER environment into the shell: + +```shell +export HAMMER_HOME=$PWD/hammer +source $HAMMER_HOME/sourceme.sh +``` + +The configuration for the example design is contained in `example.yml` and the entry script with hooks is contained in `example-vlsi`. You may go through Hammer's readme to learn about the supported configuration options and how to write hooks. + +To synthesize a design: + +```shell +make syn +``` + +The outputs are written to a log file with a timestamp and the post-synthesis results are in `build/syn-rundir`. + +Raw QoR data is available at `build/syn-rundir/reports`, and work is planned to extract this information in a more programmatic manner. + +To run place and route: +```shell +make par +``` + +If successful, the resulting chip can be opened via `./build/par-rundir/generated-scripts/open_chip`. + +To run DRC and view violations: +```shell +make drc +./build/drc-rundir/generated-scripts/view-drc +``` + +To run LVS and view violations: +```shell +make lvs +./build/lvs-rundir/generated-scripts/view-lvs +``` diff --git a/vlsi/bwrc-env.yml b/vlsi/bwrc-env.yml new file mode 100644 index 00000000..f68eab24 --- /dev/null +++ b/vlsi/bwrc-env.yml @@ -0,0 +1,7 @@ +mentor.mentor_home: "/tools/mentor" +mentor.MGLS_LICENSE_FILE: "1717@bwrcflex-1.eecs.berkeley.edu:1717@bwrcflex-2.eecs.berkeley.edu" +cadence.cadence_home: "/tools/cadence" +cadence.CDS_LIC_FILE: "5280@bwrcflex-1.eecs.berkeley.edu:5280@bwrcflex-2.eecs.berkeley.edu" +synopsys.synopsys_home: "/tools/synopsys" +synopsys.SNPSLMD_LICENSE_FILE: "1701@bwrcflex-1.eecs.berkeley.edu:1701@bwrcflex-2.eecs.berkeley.edu" +synopsys.MGLS_LICENSE_FILE: "1717@bwrcflex-1.eecs.berkeley.edu:1717@bwrcflex-2.eecs.berkeley.edu" diff --git a/vlsi/example.yml b/vlsi/example.yml index 790479c9..5711e71a 100644 --- a/vlsi/example.yml +++ b/vlsi/example.yml @@ -30,6 +30,58 @@ vlsi.core.build_system: make # Power Straps par.power_straps_mode: generate +par.generate_power_straps_method: by_tracks +par.blockage_spacing: 2.0 +par.generate_power_straps_options: + by_tracks: + strap_layers: + - M3 + - M4 + - M5 + - M6 + - M7 + - M8 + - M9 + track_width: 6 + track_spacing: 0 + power_utilization: 0.05 + power_utilization_M8: 1.0 + power_utilization_M9: 1.0 # Placement Constraints -#vlsi.inputs.placement_constraints: +vlsi.inputs.placement_constraints: + - path: "ExampleTop" + type: "toplevel" + x: 0 + y: 0 + width: 50 + height: 50 + margins: + left: 0 + right: 0 + top: 0 + bottom: 0 + +# SRAM Compiler compiler options +vlsi.core.sram_generator_tool: "sram_compiler" +vlsi.core.sram_generator_tool_path: ["SPECIFY LOCATION OF SRAM GENERATOR IN TECH PLUGIN"] +vlsi.core.sram_generator_tool_path_meta: "append" + +# Tool options. Replace with your tool plugin of choice. +# Genus options +vlsi.core.synthesis_tool: "genus" +vlsi.core.synthesis_tool_path: ["hammer-cadence-plugins/synthesis"] +vlsi.core.synthesis_tool_path_meta: "append" +synthesis.genus.version: "181" +# Innovus options +vlsi.core.par_tool: "innovus" +vlsi.core.par_tool_path: ["hammer-cadence-plugins/par"] +vlsi.core.par_tool_path_meta: "append" +par.innovus.version: "181" +par.innovus.design_flow_effort: "standard" +par.inputs.gds_merge: true +# Calibre options +vlsi.core.drc_tool: "calibre" +vlsi.core.drc_tool_path: ["hammer-cad-plugins/drc"] +vlsi.core.lvs_tool: "calibre" +vlsi.core.lvs_tool_path: ["hammer-cad-plugins/lvs"] diff --git a/vlsi/hammer b/vlsi/hammer index a27886fb..6c31fbe7 160000 --- a/vlsi/hammer +++ b/vlsi/hammer @@ -1 +1 @@ -Subproject commit a27886fb42c121f3ba5f684acaf5856b2ec293e1 +Subproject commit 6c31fbe7eb57df98c5815ae4f7ba2ba904f74b0f diff --git a/vlsi/hammer-cad-plugins b/vlsi/hammer-cad-plugins deleted file mode 160000 index 72809f53..00000000 --- a/vlsi/hammer-cad-plugins +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 72809f538c4bbe91c103de52e92baad9df6d8f9a diff --git a/vlsi/hammer-cadence-plugins b/vlsi/hammer-cadence-plugins new file mode 160000 index 00000000..a0741281 --- /dev/null +++ b/vlsi/hammer-cadence-plugins @@ -0,0 +1 @@ +Subproject commit a07412814b878c67d79f7aada598848bcb4c197c diff --git a/vlsi/hammer-mentor-plugins b/vlsi/hammer-mentor-plugins new file mode 160000 index 00000000..4daaea36 --- /dev/null +++ b/vlsi/hammer-mentor-plugins @@ -0,0 +1 @@ +Subproject commit 4daaea36f805ba71b55ceb7f5579229eac935045 diff --git a/vlsi/hammer-synopsys-plugins b/vlsi/hammer-synopsys-plugins new file mode 160000 index 00000000..e0ace734 --- /dev/null +++ b/vlsi/hammer-synopsys-plugins @@ -0,0 +1 @@ +Subproject commit e0ace7345e98e11b17ce550550c902782010e032 From fb357828415d513e36a410259cdefdd707a23f07 Mon Sep 17 00:00:00 2001 From: Harrison Liew Date: Sun, 1 Sep 2019 10:42:49 -0700 Subject: [PATCH 04/39] fix incorrect block for syn/par, but still have timing violations --- vlsi/README.md | 10 +++++++++- vlsi/example.yml | 30 ++++++++++++++++++++---------- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/vlsi/README.md b/vlsi/README.md index 0ee8978d..05179ca6 100644 --- a/vlsi/README.md +++ b/vlsi/README.md @@ -18,7 +18,15 @@ make buildfile ``` # Example design -In this example, you will be running a SHA-3 accelerator through the VLSI flow. It is assumed that you have already run through the flow to elaborate the Chisel into Verilog. +In this example, you will be running a SHA-3 accelerator through the VLSI flow. To elaborate the Sha3RocketConfig and set up all prerequisites for the build system: +```shell +export MACROCOMPILER_MODE=' --mode synflops' +export CONFIG=Sha3RocketConfig +export TOP=Sha3Accel +make buildfile +``` +Note that because the ASAP7 process does not yet have a memory compiler, synflops are elaborated instead. +>>>>>>> fix incorrect block for syn/par, but still have timing violations HAMMER's configuration is driven by a JSON/YAML format. For HAMMER, JSON and YAML files are equivalent - you can use either one since HAMMER will convert them to the same representation for itself. diff --git a/vlsi/example.yml b/vlsi/example.yml index 5711e71a..ffa7e732 100644 --- a/vlsi/example.yml +++ b/vlsi/example.yml @@ -2,8 +2,10 @@ # Technology used is ASAP7 vlsi.core.technology: asap7 vlsi.core.node: 7 -technology.asap7.tarball_dir: "SPECIFY DIR WITH ASAP7 TARBALL" -technology.asap7.install_dir: "SPECIFY EXTRACTED DIR HERE IF NOT USING TARBALL" +# Specify dir with ASAP7 tarball +technology.asap7.tarball_dir: "/tools/B/asap7" +# Specify extracted dir here if not using tarball +technology.asap7.install_dir: "/tools/B/asap7" vlsi.core.max_threads: 12 @@ -13,16 +15,17 @@ vlsi.inputs.supplies.VDD: "0.7 V" # Hammer will auto-generate a CPF for simple power designs; see hammer/src/hammer-vlsi/defaults.yml for more info vlsi.inputs.power_spec_mode: "auto" +vlsi.inputs.power_spec_type: "cpf" # Specify the setup and hold corners for ASAP7 vlsi.inputs.mmmc_corners: [ - {name: "PVT_0P63V_100C", type: "setup", voltage: "0.63 V", temp: "100 C"}, - {name: "PVT_0P77V_0C", type: "hold", voltage: "0.77 V", temp: "0 C"} + {name: "PVT_0P63V_100C", type: "setup", voltage: "0.63 V", temp: "100 C"}, + {name: "PVT_0P77V_0C", type: "hold", voltage: "0.77 V", temp: "0 C"} ] # Specify clock signals vlsi.inputs.clocks: [ - {name: "clock", period: "10ns", uncertainty: "0.1ns"} + {name: "clock", period: "20ns", uncertainty: "0.1ns"} ] # Generate Make include to aid in flow @@ -50,18 +53,25 @@ par.generate_power_straps_options: # Placement Constraints vlsi.inputs.placement_constraints: - - path: "ExampleTop" + - path: "Sha3Accel" type: "toplevel" x: 0 y: 0 - width: 50 - height: 50 + width: 500 + height: 500 margins: left: 0 right: 0 top: 0 bottom: 0 +# Pin placement constraints +vlsi.inputs.pin_mode: generated +vlsi.inputs.pin.generate_mode: semi_auto +vlsi.inputs.pin.assignments: [ + {pins: "*", layers: ["M5", "M7"], side: "bottom"} +] + # SRAM Compiler compiler options vlsi.core.sram_generator_tool: "sram_compiler" vlsi.core.sram_generator_tool_path: ["SPECIFY LOCATION OF SRAM GENERATOR IN TECH PLUGIN"] @@ -82,6 +92,6 @@ par.innovus.design_flow_effort: "standard" par.inputs.gds_merge: true # Calibre options vlsi.core.drc_tool: "calibre" -vlsi.core.drc_tool_path: ["hammer-cad-plugins/drc"] +vlsi.core.drc_tool_path: ["hammer-mentor-plugins/drc"] vlsi.core.lvs_tool: "calibre" -vlsi.core.lvs_tool_path: ["hammer-cad-plugins/lvs"] +vlsi.core.lvs_tool_path: ["hammer-mentor-plugins/lvs"] From 6bc91680cddcefcd0922a086ea5c457fedf94bbb Mon Sep 17 00:00:00 2001 From: Harrison Liew Date: Sun, 1 Sep 2019 14:12:49 -0700 Subject: [PATCH 05/39] rebased on dev --- vlsi/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/vlsi/README.md b/vlsi/README.md index 05179ca6..7df19a12 100644 --- a/vlsi/README.md +++ b/vlsi/README.md @@ -18,7 +18,7 @@ make buildfile ``` # Example design -In this example, you will be running a SHA-3 accelerator through the VLSI flow. To elaborate the Sha3RocketConfig and set up all prerequisites for the build system: +In this example, you will be running a SHA-3 accelerator through the VLSI flow in the ASAP7 process. To elaborate the Sha3RocketConfig and set up all prerequisites for the build system: ```shell export MACROCOMPILER_MODE=' --mode synflops' export CONFIG=Sha3RocketConfig @@ -26,7 +26,6 @@ export TOP=Sha3Accel make buildfile ``` Note that because the ASAP7 process does not yet have a memory compiler, synflops are elaborated instead. ->>>>>>> fix incorrect block for syn/par, but still have timing violations HAMMER's configuration is driven by a JSON/YAML format. For HAMMER, JSON and YAML files are equivalent - you can use either one since HAMMER will convert them to the same representation for itself. @@ -39,6 +38,8 @@ source $HAMMER_HOME/sourceme.sh The configuration for the example design is contained in `example.yml` and the entry script with hooks is contained in `example-vlsi`. You may go through Hammer's readme to learn about the supported configuration options and how to write hooks. +In order to install the process, edit the keys `vlsi.technology.asap7.tarball_dir` if you already have the ASAP7 tarball downloaded and `vlsi.technology.asap7.install_dir` if you have already extracted it. If omitted, Hammer will automatically download and extract the tarballs into the `build/asap7-tech-cache` directory when you first run synthesis. + To synthesize a design: ```shell From 6ad433d5c72d69a917ff8fa0c50de752b993d46d Mon Sep 17 00:00:00 2001 From: Harrison Liew Date: Sun, 1 Sep 2019 18:09:38 -0700 Subject: [PATCH 06/39] power straps fixes, sha3 w/ dco skeleton --- vlsi/Makefile | 4 +- vlsi/README.md | 11 +- vlsi/example.v | 154 +++++++++++++ vlsi/example.yml | 41 +++- vlsi/extra_libraries/dco/dco.gds | Bin 0 -> 10240 bytes vlsi/extra_libraries/dco/dco.lef | 376 +++++++++++++++++++++++++++++++ vlsi/hammer-cadence-plugins | 2 +- 7 files changed, 575 insertions(+), 13 deletions(-) create mode 100644 vlsi/example.v create mode 100644 vlsi/extra_libraries/dco/dco.gds create mode 100644 vlsi/extra_libraries/dco/dco.lef diff --git a/vlsi/Makefile b/vlsi/Makefile index 6fcedd62..f4697a9b 100644 --- a/vlsi/Makefile +++ b/vlsi/Makefile @@ -33,7 +33,7 @@ HAMMER_EXEC ?= ./example-vlsi # general rules ######################################################################################### ALL_RTL = $(TOP_FILE) $(TOP_SMEMS_FILE) $(extra_v_includes) -extra_v_includes = $(build_dir)/EICG_wrapper.v +extra_v_includes = $(build_dir)/EICG_wrapper.v $(vlsi_dir)/example.v .PHONY: default verilog default: all @@ -74,7 +74,7 @@ $(SRAM_CONF): $(SRAM_GENERATOR_CONF) # synthesis input configuration ######################################################################################### SYN_CONF = $(OBJ_DIR)/inputs.yml -GENERATED_CONFS = $(SYN_CONF) $(SRAM_CONF) +GENERATED_CONFS = $(SYN_CONF) $(if $(filter $(tech_name), asap7), , $(SRAM_CONF)) $(SYN_CONF): $(ALL_RTL) $(extra_v_includes) $(sim_top_blackboxes) mkdir -p $(dir $@) diff --git a/vlsi/README.md b/vlsi/README.md index 7df19a12..12cb6fd9 100644 --- a/vlsi/README.md +++ b/vlsi/README.md @@ -7,22 +7,17 @@ If you are a UCB-affiliate, you may be able to acquire access to the tool & tech # Initial Setup Instructions (For all technologies) Run the `init-vlsi.sh` script to pull correct versions of hammer, hammer-TOOL\_VENDOR-plugins, and the hammer-TECH\_NAME-plugins. Note the included technology 'asap7' is already included and will not submodule a tech plugin. ```shell -scripts/init-vlsi.sh TECH_NAME +./scripts/init-vlsi.sh TECH_NAME ``` An example of tool environment configuration for BWRC affiliates is given in `bwrc-env.yml`. Replace as necessary for your environment. -Finally, set up all prerequisites for the build system: -```shell -make buildfile -``` - # Example design -In this example, you will be running a SHA-3 accelerator through the VLSI flow in the ASAP7 process. To elaborate the Sha3RocketConfig and set up all prerequisites for the build system: +In this example, you will be running a SHA-3 accelerator with a dummy hard macro through the VLSI flow in the ASAP7 process. To elaborate the Sha3RocketConfig and set up all prerequisites for the build system: ```shell export MACROCOMPILER_MODE=' --mode synflops' export CONFIG=Sha3RocketConfig -export TOP=Sha3Accel +export TOP=Sha3AccelwBB make buildfile ``` Note that because the ASAP7 process does not yet have a memory compiler, synflops are elaborated instead. diff --git a/vlsi/example.v b/vlsi/example.v new file mode 100644 index 00000000..bd0d3f9d --- /dev/null +++ b/vlsi/example.v @@ -0,0 +1,154 @@ +// Extracted Sha3Accel w/ a blackbox (a dummy DCO) included inside + +module Sha3AccelwBB( // @[:example.TestHarness.Sha3RocketConfig.fir@135905.2] + input clock, // @[:example.TestHarness.Sha3RocketConfig.fir@135906.4] + input reset, // @[:example.TestHarness.Sha3RocketConfig.fir@135907.4] + output io_cmd_ready, // @[:example.TestHarness.Sha3RocketConfig.fir@135909.4] + input io_cmd_valid, // @[:example.TestHarness.Sha3RocketConfig.fir@135909.4] + input [6:0] io_cmd_bits_inst_funct, // @[:example.TestHarness.Sha3RocketConfig.fir@135909.4] + input [63:0] io_cmd_bits_rs1, // @[:example.TestHarness.Sha3RocketConfig.fir@135909.4] + input [63:0] io_cmd_bits_rs2, // @[:example.TestHarness.Sha3RocketConfig.fir@135909.4] + input io_mem_req_ready, // @[:example.TestHarness.Sha3RocketConfig.fir@135909.4] + output io_mem_req_valid, // @[:example.TestHarness.Sha3RocketConfig.fir@135909.4] + output [39:0] io_mem_req_bits_addr, // @[:example.TestHarness.Sha3RocketConfig.fir@135909.4] + output [7:0] io_mem_req_bits_tag, // @[:example.TestHarness.Sha3RocketConfig.fir@135909.4] + output [4:0] io_mem_req_bits_cmd, // @[:example.TestHarness.Sha3RocketConfig.fir@135909.4] + output [63:0] io_mem_req_bits_data, // @[:example.TestHarness.Sha3RocketConfig.fir@135909.4] + input io_mem_resp_valid, // @[:example.TestHarness.Sha3RocketConfig.fir@135909.4] + input [7:0] io_mem_resp_bits_tag, // @[:example.TestHarness.Sha3RocketConfig.fir@135909.4] + input [63:0] io_mem_resp_bits_data, // @[:example.TestHarness.Sha3RocketConfig.fir@135909.4] + output io_busy, // @[:example.TestHarness.Sha3RocketConfig.fir@135909.4] + input [13:0] col_sel_b, + input [15:0] row_sel_b, + input [7:0] code_regulator, + input dither, + input sleep_b, + output dco_clock +); + wire clock; // from dummy DCO + wire ctrl_clock; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] + wire ctrl_reset; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] + wire ctrl_io_rocc_req_val; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] + wire ctrl_io_rocc_req_rdy; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] + wire [1:0] ctrl_io_rocc_funct; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] + wire [63:0] ctrl_io_rocc_rs1; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] + wire [63:0] ctrl_io_rocc_rs2; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] + wire ctrl_io_busy; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] + wire ctrl_io_dmem_req_val; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] + wire ctrl_io_dmem_req_rdy; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] + wire [6:0] ctrl_io_dmem_req_tag; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] + wire [31:0] ctrl_io_dmem_req_addr; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] + wire [4:0] ctrl_io_dmem_req_cmd; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] + wire ctrl_io_dmem_resp_val; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] + wire [6:0] ctrl_io_dmem_resp_tag; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] + wire [63:0] ctrl_io_dmem_resp_data; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] + wire [4:0] ctrl_io_round; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] + wire ctrl_io_absorb; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] + wire [4:0] ctrl_io_aindex; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] + wire ctrl_io_init; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] + wire ctrl_io_write; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] + wire [2:0] ctrl_io_windex; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] + wire [63:0] ctrl_io_buffer_out; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] + wire dpath_clock; // @[sha3.scala 82:21:example.TestHarness.Sha3RocketConfig.fir@135936.4] + wire dpath_reset; // @[sha3.scala 82:21:example.TestHarness.Sha3RocketConfig.fir@135936.4] + wire dpath_io_absorb; // @[sha3.scala 82:21:example.TestHarness.Sha3RocketConfig.fir@135936.4] + wire dpath_io_init; // @[sha3.scala 82:21:example.TestHarness.Sha3RocketConfig.fir@135936.4] + wire dpath_io_write; // @[sha3.scala 82:21:example.TestHarness.Sha3RocketConfig.fir@135936.4] + wire [4:0] dpath_io_round; // @[sha3.scala 82:21:example.TestHarness.Sha3RocketConfig.fir@135936.4] + wire [4:0] dpath_io_aindex; // @[sha3.scala 82:21:example.TestHarness.Sha3RocketConfig.fir@135936.4] + wire [63:0] dpath_io_message_in; // @[sha3.scala 82:21:example.TestHarness.Sha3RocketConfig.fir@135936.4] + wire [63:0] dpath_io_hash_out_0; // @[sha3.scala 82:21:example.TestHarness.Sha3RocketConfig.fir@135936.4] + wire [63:0] dpath_io_hash_out_1; // @[sha3.scala 82:21:example.TestHarness.Sha3RocketConfig.fir@135936.4] + wire [63:0] dpath_io_hash_out_2; // @[sha3.scala 82:21:example.TestHarness.Sha3RocketConfig.fir@135936.4] + wire [63:0] dpath_io_hash_out_3; // @[sha3.scala 82:21:example.TestHarness.Sha3RocketConfig.fir@135936.4] + wire [1:0] _T; // @[:example.TestHarness.Sha3RocketConfig.fir@135941.4] + wire [63:0] _GEN_0; // @[sha3.scala 85:24:example.TestHarness.Sha3RocketConfig.fir@135942.4] + wire [63:0] _GEN_1; // @[sha3.scala 85:24:example.TestHarness.Sha3RocketConfig.fir@135942.4] + wire [63:0] _GEN_2; // @[sha3.scala 85:24:example.TestHarness.Sha3RocketConfig.fir@135942.4] + CtrlModule ctrl ( // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] + .clock(ctrl_clock), + .reset(ctrl_reset), + .io_rocc_req_val(ctrl_io_rocc_req_val), + .io_rocc_req_rdy(ctrl_io_rocc_req_rdy), + .io_rocc_funct(ctrl_io_rocc_funct), + .io_rocc_rs1(ctrl_io_rocc_rs1), + .io_rocc_rs2(ctrl_io_rocc_rs2), + .io_busy(ctrl_io_busy), + .io_dmem_req_val(ctrl_io_dmem_req_val), + .io_dmem_req_rdy(ctrl_io_dmem_req_rdy), + .io_dmem_req_tag(ctrl_io_dmem_req_tag), + .io_dmem_req_addr(ctrl_io_dmem_req_addr), + .io_dmem_req_cmd(ctrl_io_dmem_req_cmd), + .io_dmem_resp_val(ctrl_io_dmem_resp_val), + .io_dmem_resp_tag(ctrl_io_dmem_resp_tag), + .io_dmem_resp_data(ctrl_io_dmem_resp_data), + .io_round(ctrl_io_round), + .io_absorb(ctrl_io_absorb), + .io_aindex(ctrl_io_aindex), + .io_init(ctrl_io_init), + .io_write(ctrl_io_write), + .io_windex(ctrl_io_windex), + .io_buffer_out(ctrl_io_buffer_out) + ); + DpathModule dpath ( // @[sha3.scala 82:21:example.TestHarness.Sha3RocketConfig.fir@135936.4] + .clock(dpath_clock), + .reset(dpath_reset), + .io_absorb(dpath_io_absorb), + .io_init(dpath_io_init), + .io_write(dpath_io_write), + .io_round(dpath_io_round), + .io_aindex(dpath_io_aindex), + .io_message_in(dpath_io_message_in), + .io_hash_out_0(dpath_io_hash_out_0), + .io_hash_out_1(dpath_io_hash_out_1), + .io_hash_out_2(dpath_io_hash_out_2), + .io_hash_out_3(dpath_io_hash_out_3) + ); + ExampleDCO dco ( + .col_sel_b(col_sel_b), + .row_sel_b(row_sel_b), + .code_regulator(code_regulator), + .dither(dither), + .sleep_b(sleep_b), + .clock(dco_clock) + ); + assign _T = ctrl_io_windex[1:0]; // @[:example.TestHarness.Sha3RocketConfig.fir@135941.4] + assign _GEN_0 = dpath_io_hash_out_0; // @[sha3.scala 85:24:example.TestHarness.Sha3RocketConfig.fir@135942.4] + assign _GEN_1 = 2'h1 == _T ? dpath_io_hash_out_1 : _GEN_0; // @[sha3.scala 85:24:example.TestHarness.Sha3RocketConfig.fir@135942.4] + assign _GEN_2 = 2'h2 == _T ? dpath_io_hash_out_2 : _GEN_1; // @[sha3.scala 85:24:example.TestHarness.Sha3RocketConfig.fir@135942.4] + assign io_cmd_ready = ctrl_io_rocc_req_rdy; // @[sha3.scala 64:16:example.TestHarness.Sha3RocketConfig.fir@135921.4] + assign io_mem_req_valid = ctrl_io_dmem_req_val; // @[sha3.scala 71:20:example.TestHarness.Sha3RocketConfig.fir@135927.4] + assign io_mem_req_bits_addr = {{8'd0}, ctrl_io_dmem_req_addr}; // @[sha3.scala 74:24:example.TestHarness.Sha3RocketConfig.fir@135930.4] + assign io_mem_req_bits_tag = {{1'd0}, ctrl_io_dmem_req_tag}; // @[sha3.scala 73:23:example.TestHarness.Sha3RocketConfig.fir@135929.4] + assign io_mem_req_bits_cmd = ctrl_io_dmem_req_cmd; // @[sha3.scala 75:23:example.TestHarness.Sha3RocketConfig.fir@135931.4] + assign io_mem_req_bits_data = 2'h3 == _T ? dpath_io_hash_out_3 : _GEN_2; // @[sha3.scala 85:24:example.TestHarness.Sha3RocketConfig.fir@135942.4] + assign io_busy = ctrl_io_busy; // @[sha3.scala 69:11:example.TestHarness.Sha3RocketConfig.fir@135926.4] + assign ctrl_clock = clock; // @[:example.TestHarness.Sha3RocketConfig.fir@135918.4] + assign ctrl_reset = reset; // @[:example.TestHarness.Sha3RocketConfig.fir@135919.4] + assign ctrl_io_rocc_req_val = io_cmd_valid; // @[sha3.scala 63:26:example.TestHarness.Sha3RocketConfig.fir@135920.4] + assign ctrl_io_rocc_funct = io_cmd_bits_inst_funct[1:0]; // @[sha3.scala 65:26:example.TestHarness.Sha3RocketConfig.fir@135922.4] + assign ctrl_io_rocc_rs1 = io_cmd_bits_rs1; // @[sha3.scala 66:26:example.TestHarness.Sha3RocketConfig.fir@135923.4] + assign ctrl_io_rocc_rs2 = io_cmd_bits_rs2; // @[sha3.scala 67:26:example.TestHarness.Sha3RocketConfig.fir@135924.4] + assign ctrl_io_dmem_req_rdy = io_mem_req_ready; // @[sha3.scala 72:26:example.TestHarness.Sha3RocketConfig.fir@135928.4] + assign ctrl_io_dmem_resp_val = io_mem_resp_valid; // @[sha3.scala 78:26:example.TestHarness.Sha3RocketConfig.fir@135933.4] + assign ctrl_io_dmem_resp_tag = io_mem_resp_bits_tag[6:0]; // @[sha3.scala 79:26:example.TestHarness.Sha3RocketConfig.fir@135934.4] + assign ctrl_io_dmem_resp_data = io_mem_resp_bits_data; // @[sha3.scala 80:26:example.TestHarness.Sha3RocketConfig.fir@135935.4] + assign dpath_clock = clock; // @[:example.TestHarness.Sha3RocketConfig.fir@135938.4] + assign dpath_reset = reset; // @[:example.TestHarness.Sha3RocketConfig.fir@135939.4] + assign dpath_io_absorb = ctrl_io_absorb; // @[sha3.scala 88:19:example.TestHarness.Sha3RocketConfig.fir@135943.4] + assign dpath_io_init = ctrl_io_init; // @[sha3.scala 89:17:example.TestHarness.Sha3RocketConfig.fir@135944.4] + assign dpath_io_write = ctrl_io_write; // @[sha3.scala 90:18:example.TestHarness.Sha3RocketConfig.fir@135945.4] + assign dpath_io_round = ctrl_io_round; // @[sha3.scala 91:18:example.TestHarness.Sha3RocketConfig.fir@135946.4] + assign dpath_io_aindex = ctrl_io_aindex; // @[sha3.scala 93:19:example.TestHarness.Sha3RocketConfig.fir@135948.4] + assign dpath_io_message_in = ctrl_io_buffer_out; // @[sha3.scala 84:23:example.TestHarness.Sha3RocketConfig.fir@135940.4] +endmodule + +module ExampleDCO ( + input [13:0] col_sel_b, + input [15:0] row_sel_b, + input [7:0] code_regulator, + input dither, + input sleep_b, + output clock +); +endmodule diff --git a/vlsi/example.yml b/vlsi/example.yml index ffa7e732..8616fa33 100644 --- a/vlsi/example.yml +++ b/vlsi/example.yml @@ -45,7 +45,11 @@ par.generate_power_straps_options: - M7 - M8 - M9 - track_width: 6 + track_width: 14 + track_width_M3: 7 + track_width_M5: 24 + track_width_M8: 6 + track_width_M9: 6 track_spacing: 0 power_utilization: 0.05 power_utilization_M8: 1.0 @@ -53,7 +57,7 @@ par.generate_power_straps_options: # Placement Constraints vlsi.inputs.placement_constraints: - - path: "Sha3Accel" + - path: "Sha3AccelwBB" type: "toplevel" x: 0 y: 0 @@ -64,6 +68,13 @@ vlsi.inputs.placement_constraints: right: 0 top: 0 bottom: 0 + - path: "Sha3AccelwBB/dco" + type: "hardmacro" + x: 400 + y: 400 + width: 32 + height: 32 + orientation: "r0" # Pin placement constraints vlsi.inputs.pin_mode: generated @@ -72,6 +83,32 @@ vlsi.inputs.pin.assignments: [ {pins: "*", layers: ["M5", "M7"], side: "bottom"} ] +# Paths to extra libraries +vlsi.technology.extra_libraries_meta: "append" +vlsi.technology.extra_libraries: + - library: + nldm liberty file: "extra_libraries/dco/dco_SS.lib" + lef file: "extra_libraries/dco/dco.lef" + gds file: "extra_libraries/dco/dco.gds" + corner: + nmos: "slow" + pmos: "slow" + temperature: "100 C" + supplies: + VDD: "0.63 V" + GND: "0 V" + - library: + nldm liberty file: "extra_libraries/dco/dco_FF.lib" + lef file: "extra_libraries/dco/dco.lef" + gds file: "extra_libraries/dco/dco.gds" + corner: + nmos: "fast" + pmos: "fast" + temperature: "0 C" + supplies: + VDD: "0.77 V" + GND: "0 V" + # SRAM Compiler compiler options vlsi.core.sram_generator_tool: "sram_compiler" vlsi.core.sram_generator_tool_path: ["SPECIFY LOCATION OF SRAM GENERATOR IN TECH PLUGIN"] diff --git a/vlsi/extra_libraries/dco/dco.gds b/vlsi/extra_libraries/dco/dco.gds new file mode 100644 index 0000000000000000000000000000000000000000..e5cb24a3df152a78dc21db0693f32454f1c25e9d GIT binary patch literal 10240 zcmeI1Pi$009LIlC+SgSoY>{9K#c*oZ1WhTRB@wzN#8kkf2>}|3>GsdY8W*-H5DH$J z2-q7%V^aS>dh6CxgJ^of<<qz~Y zA{Cz^wM<2BYL+<2-&fX>)hCLP+C5LSF<0c?PQDM0gZ%x!`}|+Gjv-&_(Oyfq*`$Z@BCJ10JvPlyk4 z-09y7U^LuKN${92OtsxYIw}E8) z`j1A$2Y-)=4|3e}pAXl6mErnNKX>@-ybc8Qnh>Ayz3Fc*(|@r{U)Hbw_uo=x`|p(L zzh0*QW|@9RnZEQtmAQWqUk}vPx{ErDx(izCuiU~RU6A9>{zKgbQFlRW{WaQ0-33v1L2Lar{KM^X{~+ov z$Z_ZWqwa#JyP&oHqJ7`}JA8hBQMW+{hLeTgV^_i9C!K?t>S~&cY_>v`q=k_*!P3h z{lC$FS7)Ss5a$jc$DQrt+ylHkD*X>y&p(Xzaqa@*+y%6rzZiaIT<#ylxev&3=l$c{ z3GC^Y`v}V z8KX`0!C>}$*O_#ttLNmdz3=*D;&*aer+%Kk_s{mH2iM-C{4CTIr!Cwg*}inwVEVmt zneMaM!IRCt_tP?C$+pWk+ks(Awie%PhgvP!cKc>Kwq(h+$2VJd&XUc0RGdm#vc2ki zZx`w;*Cf zlvkeb`=fbyFnQ&V=Xg|C z#-n*W-w$O?-8$8&yFM`F=Dp7Xs*c0}`d)*qEv z&~JvZhV!lcYI~w2llKh5tJ~;3dCwqK( Date: Sun, 1 Sep 2019 18:13:11 -0700 Subject: [PATCH 07/39] shouldn't have tools/B --- vlsi/example.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/vlsi/example.yml b/vlsi/example.yml index 8616fa33..d4251ad2 100644 --- a/vlsi/example.yml +++ b/vlsi/example.yml @@ -2,10 +2,8 @@ # Technology used is ASAP7 vlsi.core.technology: asap7 vlsi.core.node: 7 -# Specify dir with ASAP7 tarball -technology.asap7.tarball_dir: "/tools/B/asap7" -# Specify extracted dir here if not using tarball -technology.asap7.install_dir: "/tools/B/asap7" +technology.asap7.tarball_dir: "SPECIFY DIR WITH ASAP7 TARBALL" +technology.asap7.install_dir: "SPECIFY EXTRACTED DIR HERE IF NOT USING TARBALL" vlsi.core.max_threads: 12 From d28077ff0b71939a501dafc74e7ec45039951df6 Mon Sep 17 00:00:00 2001 From: Harrison Liew Date: Mon, 2 Sep 2019 16:59:14 -0700 Subject: [PATCH 08/39] updated DCO collateral --- vlsi/README.md | 17 ++- vlsi/example.yml | 20 ++- vlsi/extra_libraries/dco/ExampleDCO.gds | Bin 0 -> 10240 bytes .../dco/{dco.lef => ExampleDCO.lef} | 100 ++++++------ .../dco/ExampleDCO_PVT_0P63V_100C.lib | 142 ++++++++++++++++++ .../dco/ExampleDCO_PVT_0P77V_0C.lib | 142 ++++++++++++++++++ vlsi/extra_libraries/dco/dco.gds | Bin 10240 -> 0 bytes 7 files changed, 359 insertions(+), 62 deletions(-) create mode 100644 vlsi/extra_libraries/dco/ExampleDCO.gds rename vlsi/extra_libraries/dco/{dco.lef => ExampleDCO.lef} (76%) create mode 100644 vlsi/extra_libraries/dco/ExampleDCO_PVT_0P63V_100C.lib create mode 100644 vlsi/extra_libraries/dco/ExampleDCO_PVT_0P77V_0C.lib delete mode 100644 vlsi/extra_libraries/dco/dco.gds diff --git a/vlsi/README.md b/vlsi/README.md index 12cb6fd9..29fd2bc7 100644 --- a/vlsi/README.md +++ b/vlsi/README.md @@ -1,3 +1,4 @@ +# HAMMER VLSI flow This is the starting point for a vlsi flow from this repository. This flow will not work without the necessary CAD and technology plugins for HAMMER. @@ -5,7 +6,7 @@ This flow will not work without the necessary CAD and technology plugins for HAM If you are a UCB-affiliate, you may be able to acquire access to the tool & tech plugins. # Initial Setup Instructions (For all technologies) -Run the `init-vlsi.sh` script to pull correct versions of hammer, hammer-TOOL\_VENDOR-plugins, and the hammer-TECH\_NAME-plugins. Note the included technology 'asap7' is already included and will not submodule a tech plugin. +Run the `init-vlsi.sh` script to pull correct versions of hammer, hammer-TOOL\_VENDOR-plugins, and the hammer-TECH\_NAME-plugins. Note the technologies `asap7` and `saed32` are already included and will not submodule a tech plugin. ```shell ./scripts/init-vlsi.sh TECH_NAME ``` @@ -13,15 +14,16 @@ Run the `init-vlsi.sh` script to pull correct versions of hammer, hammer-TOOL\_V An example of tool environment configuration for BWRC affiliates is given in `bwrc-env.yml`. Replace as necessary for your environment. # Example design -In this example, you will be running a SHA-3 accelerator with a dummy hard macro through the VLSI flow in the ASAP7 process. To elaborate the Sha3RocketConfig and set up all prerequisites for the build system: +## Building the design +In this example, you will be running a SHA-3 accelerator with a dummy hard macro through the VLSI flow in the ASAP7 process. To elaborate the Sha3RocketConfig (Rocketchip w/ the accelerator) and set up all prerequisites for the build system: ```shell export MACROCOMPILER_MODE=' --mode synflops' export CONFIG=Sha3RocketConfig -export TOP=Sha3AccelwBB make buildfile ``` Note that because the ASAP7 process does not yet have a memory compiler, synflops are elaborated instead. +## Using HAMMER HAMMER's configuration is driven by a JSON/YAML format. For HAMMER, JSON and YAML files are equivalent - you can use either one since HAMMER will convert them to the same representation for itself. We start by pulling the HAMMER environment into the shell: @@ -33,10 +35,15 @@ source $HAMMER_HOME/sourceme.sh The configuration for the example design is contained in `example.yml` and the entry script with hooks is contained in `example-vlsi`. You may go through Hammer's readme to learn about the supported configuration options and how to write hooks. -In order to install the process, edit the keys `vlsi.technology.asap7.tarball_dir` if you already have the ASAP7 tarball downloaded and `vlsi.technology.asap7.install_dir` if you have already extracted it. If omitted, Hammer will automatically download and extract the tarballs into the `build/asap7-tech-cache` directory when you first run synthesis. +In order to install the process, download (and optionally extract) the ASAP7 PDK tarball. Then, edit the key `vlsi.technology.asap7.tarball_dir` if you want Hammer to extract for you or `vlsi.technology.asap7.install_dir` if you have already extracted it. -To synthesize a design: +To synthesize the just the SHA-3 accelerator with the hard macro we have to change the physical top module (this step is not necessary if you are pushing the entire Rocket-chip through the VLSI flow): +```shell +export TOP=Sha3AccelwBB +rm build/inputs.yml +``` +Then, to run synthesis: ```shell make syn ``` diff --git a/vlsi/example.yml b/vlsi/example.yml index d4251ad2..1c92731e 100644 --- a/vlsi/example.yml +++ b/vlsi/example.yml @@ -82,12 +82,15 @@ vlsi.inputs.pin.assignments: [ ] # Paths to extra libraries -vlsi.technology.extra_libraries_meta: "append" +vlsi.technology.extra_libraries_meta: ["append", "deepsubst"] vlsi.technology.extra_libraries: - library: - nldm liberty file: "extra_libraries/dco/dco_SS.lib" - lef file: "extra_libraries/dco/dco.lef" - gds file: "extra_libraries/dco/dco.gds" + nldm liberty file_deepsubst_meta: "local" + nldm liberty file: "extra_libraries/dco/ExampleDCO_PVT_0P63V_100C.lib" + lef file_deepsubst_meta: "local" + lef file: "extra_libraries/dco/ExampleDCO.lef" + gds file_deepsubst_meta: "local" + gds file: "extra_libraries/dco/ExampleDCO.gds" corner: nmos: "slow" pmos: "slow" @@ -96,9 +99,12 @@ vlsi.technology.extra_libraries: VDD: "0.63 V" GND: "0 V" - library: - nldm liberty file: "extra_libraries/dco/dco_FF.lib" - lef file: "extra_libraries/dco/dco.lef" - gds file: "extra_libraries/dco/dco.gds" + nldm liberty file_deepsubst_meta: "local" + nldm liberty file: "extra_libraries/dco/ExampleDCO_PVT_0P77V_0C.lib" + lef file_deepsubst_meta: "local" + lef file: "extra_libraries/dco/ExampleDCO.lef" + gds file_deepsubst_meta: "local" + gds file: "extra_libraries/dco/ExampleDCO.gds" corner: nmos: "fast" pmos: "fast" diff --git a/vlsi/extra_libraries/dco/ExampleDCO.gds b/vlsi/extra_libraries/dco/ExampleDCO.gds new file mode 100644 index 0000000000000000000000000000000000000000..843e5dffde0888fed5ae34c73a086f90c1f56936 GIT binary patch literal 10240 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 Date: Mon, 2 Sep 2019 23:27:48 -0700 Subject: [PATCH 09/39] margins for M2 DRCs --- vlsi/example.yml | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/vlsi/example.yml b/vlsi/example.yml index 1c92731e..7e434cb6 100644 --- a/vlsi/example.yml +++ b/vlsi/example.yml @@ -22,8 +22,9 @@ vlsi.inputs.mmmc_corners: [ ] # Specify clock signals +# ASAP7 bug: period value should actually be in ps vlsi.inputs.clocks: [ - {name: "clock", period: "20ns", uncertainty: "0.1ns"} + {name: "clock", period: "1000ns", uncertainty: "0.1ns"} ] # Generate Make include to aid in flow @@ -59,17 +60,17 @@ vlsi.inputs.placement_constraints: type: "toplevel" x: 0 y: 0 - width: 500 - height: 500 + width: 300 + height: 300 margins: - left: 0 - right: 0 - top: 0 - bottom: 0 + left: 10 + right: 10 + top: 10 + bottom: 10 - path: "Sha3AccelwBB/dco" type: "hardmacro" - x: 400 - y: 400 + x: 100 + y: 100 width: 32 height: 32 orientation: "r0" From e6027677b3f36707b418c33a78f490f4fb52a5bd Mon Sep 17 00:00:00 2001 From: Harrison Liew Date: Mon, 2 Sep 2019 23:35:52 -0700 Subject: [PATCH 10/39] accidentally changed a make variable --- vlsi/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vlsi/Makefile b/vlsi/Makefile index f4697a9b..52d5b947 100644 --- a/vlsi/Makefile +++ b/vlsi/Makefile @@ -21,7 +21,7 @@ sim_name ?= vcs # needed for GenerateSimFiles, but is unused tech_name ?= asap7 tech_dir ?= $(if $(filter $(tech_name), asap7 saed32), $(vlsi_dir)/hammer/src/hammer-vlsi/technology/$(tech_name), $(vlsi_dir)/hammer-$(tech_name)-plugin/$(tech_name)) SMEMS_COMP ?= $(tech_dir)/sram-compiler.json -cMEMS_CACHE ?= $(tech_dir)/sram-cache.json +SMEMS_CACHE ?= $(tech_dir)/sram-cache.json SMEMS_HAMMER ?= $(build_dir)/$(long_name).mems.hammer.json MACROCOMPILER_MODE ?= -l $(SMEMS_CACHE) -hir $(SMEMS_HAMMER) OBJ_DIR ?= $(vlsi_dir)/build From 971809a546f266b45e85a2188978a9377bf7eb85 Mon Sep 17 00:00:00 2001 From: Harrison Liew Date: Tue, 3 Sep 2019 09:32:57 -0700 Subject: [PATCH 11/39] update submodules script --- scripts/init-submodules-no-riscv-tools.sh | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/scripts/init-submodules-no-riscv-tools.sh b/scripts/init-submodules-no-riscv-tools.sh index 8cd6ced3..627c9285 100755 --- a/scripts/init-submodules-no-riscv-tools.sh +++ b/scripts/init-submodules-no-riscv-tools.sh @@ -16,14 +16,18 @@ git config submodule.toolchains/esp-tools.update none git config --global submodule.experimental-blocks.update none # Disable updates to the FireSim submodule until explicitly requested git config submodule.sims/firesim.update none -# Disable updates to the hammer-cad-plugins repo -git config submodule.vlsi/hammer-cad-plugins.update none +# Disable updates to the hammer tool plugins repos +git config submodule.vlsi/hammer-cadence-plugins.update none +git config submodule.vlsi/hammer-synopsys-plugins.update none +git config submodule.vlsi/hammer-mentor-plugins.update none git submodule update --init --recursive #--jobs 8 # unignore riscv-tools,catapult-shell2 globally git config --unset submodule.toolchains/riscv-tools.update git config --unset submodule.toolchains/esp-tools.update git config --global --unset submodule.experimental-blocks.update -git config --unset submodule.vlsi/hammer-cad-plugins.update +git config --unset submodule.vlsi/hammer-cadence-plugins.update +git config --unset submodule.vlsi/hammer-synopsys-plugins.update +git config --unset submodule.vlsi/hammer-mentor-plugins.update # Renable firesim and init only the required submodules to provide # all required scala deps, without doing a full build-setup From cfba37afc93a66922dcd745e1d3274a84206d6a4 Mon Sep 17 00:00:00 2001 From: Harrison Liew Date: Thu, 19 Sep 2019 22:43:18 -0700 Subject: [PATCH 12/39] bump hammer, remove saed32 --- scripts/init-vlsi.sh | 2 +- vlsi/Makefile | 2 +- vlsi/example.yml | 16 +++++++++------- vlsi/hammer | 2 +- vlsi/hammer-cadence-plugins | 2 +- vlsi/hammer-mentor-plugins | 2 +- 6 files changed, 14 insertions(+), 12 deletions(-) diff --git a/scripts/init-vlsi.sh b/scripts/init-vlsi.sh index aaf015ca..bbc562d4 100755 --- a/scripts/init-vlsi.sh +++ b/scripts/init-vlsi.sh @@ -10,6 +10,6 @@ git submodule update --init --recursive vlsi/hammer-synopsys-plugins git submodule update --init --recursive vlsi/hammer-mentor-plugins # Initialize HAMMER tech plugin -if [[ $1 != *asap7* ]] && [[ $1 != *saed32* ]]; then +if [[ $1 != *asap7* ]]; then git submodule update --init --recursive vlsi/hammer-$1-plugin fi diff --git a/vlsi/Makefile b/vlsi/Makefile index 52d5b947..d3f3d45f 100644 --- a/vlsi/Makefile +++ b/vlsi/Makefile @@ -19,7 +19,7 @@ include $(base_dir)/variables.mk ######################################################################################### sim_name ?= vcs # needed for GenerateSimFiles, but is unused tech_name ?= asap7 -tech_dir ?= $(if $(filter $(tech_name), asap7 saed32), $(vlsi_dir)/hammer/src/hammer-vlsi/technology/$(tech_name), $(vlsi_dir)/hammer-$(tech_name)-plugin/$(tech_name)) +tech_dir ?= $(if $(filter $(tech_name), asap7), $(vlsi_dir)/hammer/src/hammer-vlsi/technology/$(tech_name), $(vlsi_dir)/hammer-$(tech_name)-plugin/$(tech_name)) SMEMS_COMP ?= $(tech_dir)/sram-compiler.json SMEMS_CACHE ?= $(tech_dir)/sram-cache.json SMEMS_HAMMER ?= $(build_dir)/$(long_name).mems.hammer.json diff --git a/vlsi/example.yml b/vlsi/example.yml index 7e434cb6..bf6d135d 100644 --- a/vlsi/example.yml +++ b/vlsi/example.yml @@ -1,9 +1,8 @@ # Technology Setup # Technology used is ASAP7 vlsi.core.technology: asap7 -vlsi.core.node: 7 +# Specify dir with ASAP7 tarball technology.asap7.tarball_dir: "SPECIFY DIR WITH ASAP7 TARBALL" -technology.asap7.install_dir: "SPECIFY EXTRACTED DIR HERE IF NOT USING TARBALL" vlsi.core.max_threads: 12 @@ -22,9 +21,8 @@ vlsi.inputs.mmmc_corners: [ ] # Specify clock signals -# ASAP7 bug: period value should actually be in ps vlsi.inputs.clocks: [ - {name: "clock", period: "1000ns", uncertainty: "0.1ns"} + {name: "clock", period: "1ns", uncertainty: "0.1ns"} ] # Generate Make include to aid in flow @@ -44,12 +42,11 @@ par.generate_power_straps_options: - M7 - M8 - M9 - track_width: 14 - track_width_M3: 7 - track_width_M5: 24 + track_width: 5 track_width_M8: 6 track_width_M9: 6 track_spacing: 0 + track_start: 10 power_utilization: 0.05 power_utilization_M8: 1.0 power_utilization_M9: 1.0 @@ -114,6 +111,11 @@ vlsi.technology.extra_libraries: VDD: "0.77 V" GND: "0 V" +# Because the DCO is a dummy layout, we treat it as a physical-only cell +par.inputs.physical_only_cells_mode: append +par.inputs.physical_only_cells_list: + - ExampleDCO + # SRAM Compiler compiler options vlsi.core.sram_generator_tool: "sram_compiler" vlsi.core.sram_generator_tool_path: ["SPECIFY LOCATION OF SRAM GENERATOR IN TECH PLUGIN"] diff --git a/vlsi/hammer b/vlsi/hammer index 6c31fbe7..4f06ceef 160000 --- a/vlsi/hammer +++ b/vlsi/hammer @@ -1 +1 @@ -Subproject commit 6c31fbe7eb57df98c5815ae4f7ba2ba904f74b0f +Subproject commit 4f06ceef41c0e3d4a9a5f000cf5a120729edc85d diff --git a/vlsi/hammer-cadence-plugins b/vlsi/hammer-cadence-plugins index a9762c34..06ce365b 160000 --- a/vlsi/hammer-cadence-plugins +++ b/vlsi/hammer-cadence-plugins @@ -1 +1 @@ -Subproject commit a9762c344ea247eb2174e720bf8507daf3226933 +Subproject commit 06ce365b36e4b8520372968a5ef2a301afe8d5d6 diff --git a/vlsi/hammer-mentor-plugins b/vlsi/hammer-mentor-plugins index 4daaea36..33ccdccf 160000 --- a/vlsi/hammer-mentor-plugins +++ b/vlsi/hammer-mentor-plugins @@ -1 +1 @@ -Subproject commit 4daaea36f805ba71b55ceb7f5579229eac935045 +Subproject commit 33ccdccf2c04a26cceeeb03a29b9cfad38908328 From 29898bb677581f79a0ff8c94c7539cd4f63f7f76 Mon Sep 17 00:00:00 2001 From: Harrison Liew Date: Mon, 23 Sep 2019 10:20:42 -0700 Subject: [PATCH 13/39] move documentation to docs/ and new Makefile plumbing --- docs/VLSI/HAMMER.rst | 70 ++++++++++++++++++++++++++++++++++++++++-- vlsi/Makefile | 21 ++++++++++--- vlsi/README.md | 72 -------------------------------------------- vlsi/example.yml | 10 +++--- vlsi/hammer | 2 +- 5 files changed, 88 insertions(+), 87 deletions(-) delete mode 100644 vlsi/README.md diff --git a/docs/VLSI/HAMMER.rst b/docs/VLSI/HAMMER.rst index c0c77824..c472b167 100644 --- a/docs/VLSI/HAMMER.rst +++ b/docs/VLSI/HAMMER.rst @@ -24,8 +24,8 @@ Hooks are modifications to steps or actions that are programmatically defined in Tool Plugins ============ -Hammer supports separately managed plugins for different CAD tool vendors. -The types of tools (in there hammer names) supported currently include: +Hammer supports separately managed plugins for different CAD tool vendors. You may be able to acquire access to the included Cadence, Synopsys, and Mentor Graphics plugins with permission from the respective CAD tool vendor. +The types of tools (by HAMMER names) supported currently include: * synthesis * par @@ -48,7 +48,11 @@ This class should be a subclass of ``HammerTool``, which will be a su Technology Plugins ================== -Hammer supports separately managed plugins for different technologies. +Hammer supports separately managed plugins for different technologies. You may be able to acquire access to certain pre-built technology plugins with permission from the technology vendor. Or, to build your own tech plugin, you need at least a ``.tech.json`` and ``defaults.yml``. An ``__init__.py`` is optional if there are any technology-specific methods or hooks to run. Refer to the ASAP7 plugin and associated documentation for more information. + +In order to configure your technology of choice, you will need to set several configuration variables. +First, you need to choose the technology, for example ``vlsi.core.technology: asap7`` and point to the location with the PDK tarball with ``technology..tarball_dir`` or pre-installed directory with ``technology..install_dir``. +Technology-specific options such as supplies, MMMC corners, metal layers, etc. will need to be matched to the technology in their respective ``vlsi.inputs...`` configurations. Configuration ============= @@ -56,3 +60,63 @@ Configuration To configure a hammer flow the user needs to supply a yaml or json configuration file the chooses the tool and technology plugins and versions as well as any design specific configuration APIs. You can see the current set of all available Hammer APIs `here `__. + +ASAP7 Tutorial +============== +The ``vlsi`` folder of this repository contains an example HAMMER flow with the SHA-3 accelerator and a dummy hard macro in the ASAP7 PDK. It is tested with the Cadence and Mentor tool plugins. + +Initial Setup +------------- +Run ``./scripts/init-vlsi.sh TECH_HAME`` to pull the HAMMER & plugin submodules. Note that for technologies other than ASAP7, the tech submodule must be added in the ``vlsi`` folder first. + +An example of tool environment configuration for BWRC affiliates is given in ``bwrc-env.yml``. Replace paths as necessary for your build environment. + +Pull the HAMMER environment into the shell: + +:: + export HAMMER_HOME=$PWD/hammer + source $HAMMER_HOME/sourceme.sh + +Building the Design +------------------- +To elaborate the Sha3RocketConfig (Rocketchip w/ the accelerator) and set up all prerequisites for the build system to push just the accelerator + hard macro through the flow: + +:: + export MACROCOMPILER_MODE=' --mode synflops' + export CONFIG=Sha3RocketConfig + export VLSI_TOP=Sha3AccelwBB + make buildfile + +Note that because the ASAP7 process does not yet have a memory compiler, synflops are elaborated instead. + +Running the VLSI Flow +--------------------- +The configuration for this example is contained in ``example.yml`` and the entry script with placeholders for hooks is contained in ``example-vlsi``. Before continuing, ensure you have the `ASAP7 PDK `__ tarball downloaded (but not extracted) and point the ``technology.asap7.tarball_dir`` to the tarball directory. + +To synthesize, type ``make syn``. + +Post-synthesis results are in ``build/syn-rundir``. Raw QoR data is available at ``build/syn-rundir/reports``, and methods to extract this information for design space exploration are a WIP. + +To place and route, type ``make par``. + +If successful, the resulting chip can be opened via ``./build/par-rundir/generated-scripts/open_chip``. + +Intermediate database are written in ``build/par-rundir`` between each step of the ``par`` action, and can be restored in an interactive Innovus session as desired for debugging purposes. Compressed timing reports are found in ``build/par-rundir/timingReports``. + +To run DRC & LVS, and view the results: + +:: + make drc + ./build/drc-rundir/generated-scripts/view-drc + make lvs + ./build/lvs-rundir/generated-scripts/view-lvs + +Some DRC errors are expected from this PDK, as explained in the `ASAP7 plugin readme `__ + +Alternative RTL Flows +--------------------- +The Make-based build system provided supports using HAMMER without using RTL generated by Chipyard. To push a custom verilog module through, one only needs to export the following environment variables before ``make buildfile``. + +:: + export CUSTOM_VLOG= + export VLSI_TOP= diff --git a/vlsi/Makefile b/vlsi/Makefile index d3f3d45f..3f493c6e 100644 --- a/vlsi/Makefile +++ b/vlsi/Makefile @@ -28,12 +28,20 @@ OBJ_DIR ?= $(vlsi_dir)/build ENV_YML ?= $(vlsi_dir)/bwrc-env.yml INPUT_CONFS ?= example.yml HAMMER_EXEC ?= ./example-vlsi +VLSI_TOP ?= $(TOP) ######################################################################################### # general rules ######################################################################################### -ALL_RTL = $(TOP_FILE) $(TOP_SMEMS_FILE) $(extra_v_includes) +ALL_RTL = $(TOP_FILE) $(TOP_SMEMS_FILE) extra_v_includes = $(build_dir)/EICG_wrapper.v $(vlsi_dir)/example.v +ifneq ($(CUSTOM_VLOG), ) + VLSI_RTL = $(CUSTOM_VLOG) + VLSI_BB = /dev/null +else + VLSI_RTL = $(ALL_RTL) $(extra_v_includes) + VLSI_BB = $(sim_top_blackboxes) +endif .PHONY: default verilog default: all @@ -74,14 +82,17 @@ $(SRAM_CONF): $(SRAM_GENERATOR_CONF) # synthesis input configuration ######################################################################################### SYN_CONF = $(OBJ_DIR)/inputs.yml -GENERATED_CONFS = $(SYN_CONF) $(if $(filter $(tech_name), asap7), , $(SRAM_CONF)) +GENERATED_CONFS = $(SYN_CONF) +ifeq ($(CUSTOM_VLOG), ) + GENERATED_CONFS += $(if $(filter $(tech_name), asap7), , $(SRAM_CONF)) +endif -$(SYN_CONF): $(ALL_RTL) $(extra_v_includes) $(sim_top_blackboxes) +$(SYN_CONF): $(VLSI_RTL) $(VLSI_BB) mkdir -p $(dir $@) echo "synthesis.inputs:" > $@ - echo " top_module: $(TOP)" >> $@ + echo " top_module: $(VLSI_TOP)" >> $@ echo " input_files:" >> $@ - for x in $(ALL_RTL) $(extra_v_includes) `cat $(sim_top_blackboxes)`; do \ + for x in $(VLSI_RTL) `cat $(VLSI_BB)`; do \ echo ' - "'$$x'"' >> $@; \ done diff --git a/vlsi/README.md b/vlsi/README.md deleted file mode 100644 index 29fd2bc7..00000000 --- a/vlsi/README.md +++ /dev/null @@ -1,72 +0,0 @@ -# HAMMER VLSI flow -This is the starting point for a vlsi flow from this repository. - -This flow will not work without the necessary CAD and technology plugins for HAMMER. - -If you are a UCB-affiliate, you may be able to acquire access to the tool & tech plugins. - -# Initial Setup Instructions (For all technologies) -Run the `init-vlsi.sh` script to pull correct versions of hammer, hammer-TOOL\_VENDOR-plugins, and the hammer-TECH\_NAME-plugins. Note the technologies `asap7` and `saed32` are already included and will not submodule a tech plugin. -```shell -./scripts/init-vlsi.sh TECH_NAME -``` - -An example of tool environment configuration for BWRC affiliates is given in `bwrc-env.yml`. Replace as necessary for your environment. - -# Example design -## Building the design -In this example, you will be running a SHA-3 accelerator with a dummy hard macro through the VLSI flow in the ASAP7 process. To elaborate the Sha3RocketConfig (Rocketchip w/ the accelerator) and set up all prerequisites for the build system: -```shell -export MACROCOMPILER_MODE=' --mode synflops' -export CONFIG=Sha3RocketConfig -make buildfile -``` -Note that because the ASAP7 process does not yet have a memory compiler, synflops are elaborated instead. - -## Using HAMMER -HAMMER's configuration is driven by a JSON/YAML format. For HAMMER, JSON and YAML files are equivalent - you can use either one since HAMMER will convert them to the same representation for itself. - -We start by pulling the HAMMER environment into the shell: - -```shell -export HAMMER_HOME=$PWD/hammer -source $HAMMER_HOME/sourceme.sh -``` - -The configuration for the example design is contained in `example.yml` and the entry script with hooks is contained in `example-vlsi`. You may go through Hammer's readme to learn about the supported configuration options and how to write hooks. - -In order to install the process, download (and optionally extract) the ASAP7 PDK tarball. Then, edit the key `vlsi.technology.asap7.tarball_dir` if you want Hammer to extract for you or `vlsi.technology.asap7.install_dir` if you have already extracted it. - -To synthesize the just the SHA-3 accelerator with the hard macro we have to change the physical top module (this step is not necessary if you are pushing the entire Rocket-chip through the VLSI flow): -```shell -export TOP=Sha3AccelwBB -rm build/inputs.yml -``` - -Then, to run synthesis: -```shell -make syn -``` - -The outputs are written to a log file with a timestamp and the post-synthesis results are in `build/syn-rundir`. - -Raw QoR data is available at `build/syn-rundir/reports`, and work is planned to extract this information in a more programmatic manner. - -To run place and route: -```shell -make par -``` - -If successful, the resulting chip can be opened via `./build/par-rundir/generated-scripts/open_chip`. - -To run DRC and view violations: -```shell -make drc -./build/drc-rundir/generated-scripts/view-drc -``` - -To run LVS and view violations: -```shell -make lvs -./build/lvs-rundir/generated-scripts/view-lvs -``` diff --git a/vlsi/example.yml b/vlsi/example.yml index bf6d135d..f68bbd12 100644 --- a/vlsi/example.yml +++ b/vlsi/example.yml @@ -43,8 +43,6 @@ par.generate_power_straps_options: - M8 - M9 track_width: 5 - track_width_M8: 6 - track_width_M9: 6 track_spacing: 0 track_start: 10 power_utilization: 0.05 @@ -60,10 +58,10 @@ vlsi.inputs.placement_constraints: width: 300 height: 300 margins: - left: 10 - right: 10 - top: 10 - bottom: 10 + left: 0 + right: 0 + top: 0 + bottom: 1.08 #must be at least this number - path: "Sha3AccelwBB/dco" type: "hardmacro" x: 100 diff --git a/vlsi/hammer b/vlsi/hammer index 4f06ceef..b837b3fa 160000 --- a/vlsi/hammer +++ b/vlsi/hammer @@ -1 +1 @@ -Subproject commit 4f06ceef41c0e3d4a9a5f000cf5a120729edc85d +Subproject commit b837b3fa321cce78998811d3bc842463e58e5745 From 4c443d20776c8ec944ccd7780785279313e98266 Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Wed, 25 Sep 2019 10:26:40 -0700 Subject: [PATCH 14/39] start firrtl transform docs [skip ci] --- docs/Customization/Firrtl-Transforms.rst | 64 ++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 docs/Customization/Firrtl-Transforms.rst diff --git a/docs/Customization/Firrtl-Transforms.rst b/docs/Customization/Firrtl-Transforms.rst new file mode 100644 index 00000000..0cc396ad --- /dev/null +++ b/docs/Customization/Firrtl-Transforms.rst @@ -0,0 +1,64 @@ +.. _firrtl-transforms: + +Adding a Firrtl Transform +========================= + +After generating a ``.fir`` file from the Chisel generator, this ``.fir`` file is passed to +FIRRTL. FIRRTL then goes ahead and modifies the ``.fir`` IR with a series of tranforms that can modify +the circuit and then converts it to Verilog. + +Where to add transforms +----------------------- + +The main location to add tranforms is within the ``tools/barstools`` project. +Inside the ``tranforms`` package, the FIRRTL compiler is called twice, +first on the top-level circuit, then on the test harness. This is because we want to separate out +the harness and all the modules associated with it from the top-level design under test. + +If you want to add transforms to just modify the DUT, you can add them to ``topTransforms``. + +If you want to add transforms to just modify the test harness, you can add them to ``harnessTransforms``. + +Examples of transforms +---------------------- + +There are multiple examples of transforms that you can apply and are spread across the FIRRTL ecosystem. +Within FIRRTL there is a default set of supported transforms located in https://github.com/freechipsproject/firrtl/tree/master/src/main/scala/firrtl/transforms. +This includes transforms that can flatten modules (``Flatten``), group modules together (``GroupAndDedup``), and more. + +Transforms can be standalone or can take annotations as input. Annotations are FIRRTL specific ``json`` files that +are used to pass information into FIRRTL transforms (e.g. what modules to flatten, group, etc). Annotations can be added to the code by +adding them to your Chisel source (which will generate the ``json`` code for you) or by creating the ``.json`` file and adding it to the FIRRTL compiler. + +Here is an example of grouping a series of modules by specifying the ``.json`` file: + +.. code-block:: json + + [ + { + "class": "firrtl.transforms.GroupAnnotation", + "components": [ + "BeagleChipTop.BeagleChipTop.instance1", + "BeagleChipTop.BeagleChipTop.instance2", + ], + "newModule": "NewModule", + "newInstance": "newModInst" + } + ] + + +Once created then you can add this to the FIRRTL compiler by modifying ``common.mk`` and adding the particu + +.. code-block:: none + + -faf yourAnnoFile.json + + + +If you are interested in writing FIRRTL transforms please refer to the FIRRTL documentation located here: +https://github.com/freechipsproject/firrtl/wiki. + +The main Chipyard tranforms that are applied to the top and are located in the ``tools/barstools``. + +- Talk about .json annotations + From 50dfe03278c906fbbbb853a35440b17c0a7d89c3 Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Wed, 25 Sep 2019 12:30:48 -0700 Subject: [PATCH 15/39] talk about fesvr and combine with dtm/jtag [skip ci] --- docs/Advanced-Usage/Chip-Communication.rst | 76 ++++++++++++++++++++++ docs/Advanced-Usage/DTM-Debugging.rst | 47 ------------- docs/Advanced-Usage/index.rst | 2 +- 3 files changed, 77 insertions(+), 48 deletions(-) create mode 100644 docs/Advanced-Usage/Chip-Communication.rst delete mode 100644 docs/Advanced-Usage/DTM-Debugging.rst diff --git a/docs/Advanced-Usage/Chip-Communication.rst b/docs/Advanced-Usage/Chip-Communication.rst new file mode 100644 index 00000000..8f31d931 --- /dev/null +++ b/docs/Advanced-Usage/Chip-Communication.rst @@ -0,0 +1,76 @@ +.. _chip-communication: + +Communicating with the Chip/DUT +=============================== + +What good is a chip if it can't communicate with the outside world? Chipyard designs communicate to the outside world in +one of two ways: + +* using the Front-End Server (FESVR) +* using Rocket Chip's JTAG/DTM interface. + +Debugging with the Front-End Server (FESVR) +------------------------------------------- + +By default, Chipyard simulations are setup to use the Front-End Server (FESVR) and extra infrastructure to bringup the DUT. However, FESVR can also be used to +bringup a DUT/Chip when a tapeout is completed. FESVR is a C++ library that gives a simple API to reset, send messages, and run programs on a DUT. +It can be added used simulators (VCS, Verilator, FireSim) as well as in a bringup sequence for a taped out chip. + +In the case of a simulator like VCS/Verilator, FESVR functions are converted into Tethered Serial Interface (TSI) commands. +These TSI commands are simple R/W commands that are able to probe the DUT's memory space. In simulation, these TSI commands connect to +a ``SimSerial`` (located in the ``generators/testchipip`` project) simulation C++ class that is added to simulation. This ``SimSerial`` +device sends the TSI command to the DUT which contains a ``SerialAdapter`` (located in the ``generators/testchipip`` project) that converts +the TSI commands to TileLink requests. In simulation, FESVR resets the DUT, and writes into memory the test program. This is currently the fastest +mechanism to simulate the DUT. + +In the case of a chip tapeout bringup, FESVR is used as a library ... + +to a main C++ that is run to communicate to a physical chip. In this case, FESVR is normally modified to specify the communication +medium (i.e. send message with TSI over pins in a particular protocol). + +Debugging with DTM/JTAG +----------------------- + +Chipyard is not setup to use the Debug Test Module (DTM) to bringup the core. +This is because the DTM executes a small loop of code to write the test binary byte-wise into memory +while the default ``SimSerial``/``SerialAdapter``/``FESVR`` interface directly writes to memory. +However, if you want to use JTAG, you must do the following steps to setup a DTM enabled system. + +Creating a DTM/JTAG Config +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +First, a DTM config must be created for the system that you want to create. +This involves specifying the SoC top-level to add a DTM as well as configuring that DTM to use JTAG. + +.. literalinclude:: ../../generators/example/src/main/scala/RocketConfigs.scala + :language: scala + :start-after: DOC include start: JtagRocket + :end-before: DOC include end: JtagRocket + +In this example, the ``WithDTMTop`` mixin specifies that the top-level SoC will instantiate a DTM. +The ``WithJtagDTM`` will configure that instantiated DTM to use JTAG as the bringup method (note: this can be removed if you want a DTM-only bringup). +The rest of the mixins specify the rest of the system (cores, accelerators, etc). + +Starting the DTM Simulation +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +After creating the config, call the ``make`` command like the following: + +.. code-block:: bash + + cd sims/verilator + # or + cd sims/vcs + + make CONFIG=DTMBoomConfig TOP=TopWithDTM MODEL=TestHarnessWithDTM + +In this example, this will use the config that you previously specified, as well as set the other parameters that are needed to satisfy the build system. +After that point, you should have a JTAG enabled simulation that you can attach to using OpenOCD and GDB! + +Debugging with JTAG +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Please refer to the following resources on how to debug with JTAG. + +* https://github.com/chipsalliance/rocket-chip#-debugging-with-gdb +* https://github.com/riscv/riscv-isa-sim#debugging-with-gdb diff --git a/docs/Advanced-Usage/DTM-Debugging.rst b/docs/Advanced-Usage/DTM-Debugging.rst deleted file mode 100644 index 787a73ab..00000000 --- a/docs/Advanced-Usage/DTM-Debugging.rst +++ /dev/null @@ -1,47 +0,0 @@ -Debugging with DTM/JTAG -=============================== - -By default, Chipyard is not setup to use the Debug Test Module (DTM) to bringup the core. -Instead, Chipyard uses TSI commands to bringup the core (which normally results in a faster simulation). -TSI simulations use the SimSerial interface to directly write the test binary into memory, while the DTM -executes a small loop of code to write the test binary byte-wise into memory. -However, if you want to use JTAG, you must do the following steps to setup a DTM enabled system. - -Creating a DTM/JTAG Config -------------------------------------------- - -First, a DTM config must be created for the system that you want to create. -This involves specifying the SoC top-level to add a DTM as well as configuring that DTM to use JTAG. - -.. literalinclude:: ../../generators/example/src/main/scala/RocketConfigs.scala - :language: scala - :start-after: DOC include start: JtagRocket - :end-before: DOC include end: JtagRocket - -In this example, the ``WithDTMTop`` mixin specifies that the top-level SoC will instantiate a DTM. -The ``WithJtagDTM`` will configure that instantiated DTM to use JTAG as the bringup method (note: this can be removed if you want a DTM-only bringup). -The rest of the mixins specify the rest of the system (cores, accelerators, etc). - -Starting the DTM Simulation -------------------------------------------- - -After creating the config, call the ``make`` command like the following: - -.. code-block:: bash - - cd sims/verilator - # or - cd sims/vcs - - make CONFIG=DTMBoomConfig TOP=TopWithDTM MODEL=TestHarnessWithDTM - -In this example, this will use the config that you previously specified, as well as set the other parameters that are needed to satisfy the build system. -After that point, you should have a JTAG enabled simulation that you can attach to using OpenOCD and GDB! - -Debugging with JTAG -------------------------------------------------------- - -Please refer to the following resources on how to debug with JTAG. - -* https://github.com/chipsalliance/rocket-chip#-debugging-with-gdb -* https://github.com/riscv/riscv-isa-sim#debugging-with-gdb diff --git a/docs/Advanced-Usage/index.rst b/docs/Advanced-Usage/index.rst index 2a8824b2..4864ce7a 100644 --- a/docs/Advanced-Usage/index.rst +++ b/docs/Advanced-Usage/index.rst @@ -8,5 +8,5 @@ They expect you to know about Chisel, Parameters, Configs, etc. :maxdepth: 2 :caption: Advanced Usage: - DTM-Debugging + Chip-Communication Resources From 9199a02e1e8a9517336e1c425d3f5e92fb23bcc6 Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Wed, 25 Sep 2019 11:18:25 -0700 Subject: [PATCH 16/39] add literal references | cleanup firrtl-transform-docs [ci skip] --- common.mk | 2 + docs/Customization/Firrtl-Transforms.rst | 59 +++++++++++-------- .../src/main/scala/TargetMixins.scala | 2 + 3 files changed, 38 insertions(+), 25 deletions(-) diff --git a/common.mk b/common.mk index 442c62f9..112285c2 100644 --- a/common.mk +++ b/common.mk @@ -53,10 +53,12 @@ HARNESS_CONF_FLAGS = -thconf $(HARNESS_SMEMS_CONF) TOP_TARGETS = $(TOP_FILE) $(TOP_SMEMS_CONF) $(TOP_ANNO) $(TOP_FIR) $(sim_top_blackboxes) HARNESS_TARGETS = $(HARNESS_FILE) $(HARNESS_SMEMS_CONF) $(HARNESS_ANNO) $(HARNESS_FIR) $(sim_harness_blackboxes) +# DOC include start: FirrtlCompiler .INTERMEDIATE: firrtl_temp $(TOP_TARGETS) $(HARNESS_TARGETS): firrtl_temp firrtl_temp: $(FIRRTL_FILE) $(ANNO_FILE) cd $(base_dir) && $(SBT) "project tapeout" "runMain barstools.tapeout.transforms.GenerateTopAndHarness -o $(TOP_FILE) -tho $(HARNESS_FILE) -i $(FIRRTL_FILE) --syn-top $(TOP) --harness-top $(VLOG_MODEL) -faf $(ANNO_FILE) -tsaof $(TOP_ANNO) -tdf $(sim_top_blackboxes) -tsf $(TOP_FIR) -thaof $(HARNESS_ANNO) -hdf $(sim_harness_blackboxes) -thf $(HARNESS_FIR) $(REPL_SEQ_MEM) $(HARNESS_CONF_FLAGS) -td $(build_dir)" +# DOC include end: FirrtlCompiler # This file is for simulation only. VLSI flows should replace this file with one containing hard SRAMs MACROCOMPILER_MODE ?= --mode synflops diff --git a/docs/Customization/Firrtl-Transforms.rst b/docs/Customization/Firrtl-Transforms.rst index 0cc396ad..4d947522 100644 --- a/docs/Customization/Firrtl-Transforms.rst +++ b/docs/Customization/Firrtl-Transforms.rst @@ -3,21 +3,24 @@ Adding a Firrtl Transform ========================= -After generating a ``.fir`` file from the Chisel generator, this ``.fir`` file is passed to -FIRRTL. FIRRTL then goes ahead and modifies the ``.fir`` IR with a series of tranforms that can modify -the circuit and then converts it to Verilog. +After writing the Chisel RTL, you can make further modifications by adding transforms during the FIRRTL compilation phase. +As mentioned in Section <>, transforms are modifications that happen on the FIRRTL IR that can modify a circuit. +Transforms are a powerful tool to take in the FIRRTL IR that is emitted from Chisel and run analysis (https://www.youtube.com/watch?v=FktjrjRVBoY) or convert the circuit into a new form. Where to add transforms ----------------------- -The main location to add tranforms is within the ``tools/barstools`` project. -Inside the ``tranforms`` package, the FIRRTL compiler is called twice, -first on the top-level circuit, then on the test harness. This is because we want to separate out -the harness and all the modules associated with it from the top-level design under test. +In Chipyard, the FIRRTL compiler is called multiple times to create a "Top" file that has the DUT and a "Harness" file that has all harness collateral. +This done by the ``tapeout`` SBT project (located in ``tools/barstools/tapeout``) which calls ``GenerateTopAndHarness`` (a function that wraps the multiple FIRRTL compiler calls and extra transforms). -If you want to add transforms to just modify the DUT, you can add them to ``topTransforms``. +.. literalinclude:: ../../common.mk + :language: make + :start-after: DOC include start: FirrtlCompiler + :end-before: DOC include end: FirrtlCompiler -If you want to add transforms to just modify the test harness, you can add them to ``harnessTransforms``. +If you look inside of the `tools/barstools/tapeout/src/main/scala/transforms/Generate.scala `__ file, +you can see that FIRRTL invoked twice, once for the "Top" and once for the "Harness". If you want to add transforms to just modify the DUT, you can add them to ``topTransforms``. +Otherwise, if you want to add transforms to just modify the test harness, you can add them to ``harnessTransforms``. Examples of transforms ---------------------- @@ -26,11 +29,20 @@ There are multiple examples of transforms that you can apply and are spread acro Within FIRRTL there is a default set of supported transforms located in https://github.com/freechipsproject/firrtl/tree/master/src/main/scala/firrtl/transforms. This includes transforms that can flatten modules (``Flatten``), group modules together (``GroupAndDedup``), and more. -Transforms can be standalone or can take annotations as input. Annotations are FIRRTL specific ``json`` files that -are used to pass information into FIRRTL transforms (e.g. what modules to flatten, group, etc). Annotations can be added to the code by -adding them to your Chisel source (which will generate the ``json`` code for you) or by creating the ``.json`` file and adding it to the FIRRTL compiler. +Transforms can be standalone or can take annotations as input. Annotations are used to pass information between FIRRTL transforms. This includes information on +what modules to flatten, group, and more. Annotations can be added to the code by +adding them to your Chisel source or by creating the ``.json`` file and adding it to the FIRRTL compiler (note: adding to the Chisel source will add the ``json`` snippet into the build system for you). +**The recommended way to annotate something is to do it in the Chisel source**. -Here is an example of grouping a series of modules by specifying the ``.json`` file: +Here is an example of adding an annotation within the Chisel source. This example is taken from the +``firechip`` project and uses an annotation to mark BOOM's register file for optimization: + +.. literalinclude:: ../../generators/firechip/src/main/scala/TargetMixins.scala + :language: make + :start-after: DOC include start: ChiselAnnotation + :end-before: DOC include end: ChiselAnnotation + +Here is an example of grouping a series of modules by specifying the ``.json`` file. .. code-block:: json @@ -44,21 +56,18 @@ Here is an example of grouping a series of modules by specifying the ``.json`` f "newModule": "NewModule", "newInstance": "newModInst" } - ] + ] +In this case, the specific syntax depends on the type of annotation. The best way to figure out +what the ``json`` file should contain is to first try to annotate in the Chisel +source and then see what the ``json`` output gives and copy that format. -Once created then you can add this to the FIRRTL compiler by modifying ``common.mk`` and adding the particu - -.. code-block:: none - - -faf yourAnnoFile.json - +Once ``yourAnnoFile.json`` is created then you can add ``-faf yourAnnoFile.json`` to the FIRRTL compiler invocation in ``common.mk``. +.. literalinclude:: ../../common.mk + :language: make + :start-after: DOC include start: FirrtlCompiler + :end-before: DOC include end: FirrtlCompiler If you are interested in writing FIRRTL transforms please refer to the FIRRTL documentation located here: https://github.com/freechipsproject/firrtl/wiki. - -The main Chipyard tranforms that are applied to the top and are located in the ``tools/barstools``. - -- Talk about .json annotations - diff --git a/generators/firechip/src/main/scala/TargetMixins.scala b/generators/firechip/src/main/scala/TargetMixins.scala index f36cf021..9a8dd739 100644 --- a/generators/firechip/src/main/scala/TargetMixins.scala +++ b/generators/firechip/src/main/scala/TargetMixins.scala @@ -108,6 +108,7 @@ trait ExcludeInvalidBoomAssertions extends LazyModuleImp { trait CanHaveMultiCycleRegfileImp { val outer: utilities.HasBoomAndRocketTiles val boomCores = outer.boomTiles.map(tile => tile.module.core) + // DOC include start: ChiselAnnotation boomCores.foreach({ core => core.iregfile match { case irf: boom.exu.RegisterFileSynthesizable => annotate(MemModelAnnotation(irf.regfile)) @@ -119,6 +120,7 @@ trait CanHaveMultiCycleRegfileImp { case _ => Nil } }) + // DOC include end: ChiselAnnotation outer.rocketTiles.foreach({ tile => annotate(MemModelAnnotation(tile.module.core.rocketImpl.rf.rf)) From e90d53e31eef6437f6d8d3e1340f02587f575ec6 Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Wed, 25 Sep 2019 13:20:16 -0700 Subject: [PATCH 17/39] add tranforms to index [ci skip] --- docs/Customization/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/Customization/index.rst b/docs/Customization/index.rst index c0432e73..7592ff83 100644 --- a/docs/Customization/index.rst +++ b/docs/Customization/index.rst @@ -17,3 +17,4 @@ Hit next to get started! Adding-An-Accelerator Memory-Hierarchy Boot-Process + Firrtl-Transforms From 17578ddc93d575cdedce610cce23710db44dab4e Mon Sep 17 00:00:00 2001 From: Harrison Liew Date: Wed, 25 Sep 2019 15:11:41 -0700 Subject: [PATCH 18/39] [skip ci] docs bump for review --- docs/VLSI/HAMMER.rst | 189 ++++++++++++++---- vlsi/example.yml | 33 ++- vlsi/extra_libraries/dco/ExampleDCO.gds | Bin 10240 -> 9472 bytes vlsi/extra_libraries/dco/ExampleDCO.lef | 115 +++++------ .../dco/ExampleDCO_PVT_0P63V_100C.lib | 10 +- .../dco/ExampleDCO_PVT_0P77V_0C.lib | 10 +- 6 files changed, 233 insertions(+), 124 deletions(-) diff --git a/docs/VLSI/HAMMER.rst b/docs/VLSI/HAMMER.rst index c472b167..28de651f 100644 --- a/docs/VLSI/HAMMER.rst +++ b/docs/VLSI/HAMMER.rst @@ -4,7 +4,9 @@ Core HAMMER `HAMMER `__ is a physical design generator that wraps around vendor specific technologies and tools to provide a single API to create ASICs. HAMMER allows for reusability in ASIC design while still providing the designers leeway to make their own modifications. -For more information, read the `HAMMER paper `__ and see the `GitHub repository `__. +For more information, read the `HAMMER paper `__ and see the `GitHub repository `__ and associated documentation. + +Hammer implements a VLSI flow using the following high-level constructs: Actions ------- @@ -21,11 +23,18 @@ Hooks Hooks are modifications to steps or actions that are programmatically defined in a Hammer configuration. +Configuration (Hammer IR) +========================= + +To configure a Hammer flow, supply a set yaml or json configuration files that chooses the tool and technology plugins and versions as well as any design specific configuration options. Collectively, this configuration API is referred to as Hammer IR and can be generated from higher-level abstractions. + +The current set of all available Hammer APIs is codified `here `__. + Tool Plugins ============ -Hammer supports separately managed plugins for different CAD tool vendors. You may be able to acquire access to the included Cadence, Synopsys, and Mentor Graphics plugins with permission from the respective CAD tool vendor. -The types of tools (by HAMMER names) supported currently include: +Hammer supports separately managed plugins for different CAD tool vendors. You may be able to acquire access to the included Cadence, Synopsys, and Mentor plugins repositories with permission from the respective CAD tool vendor. +The types of tools (by Hammer names) supported currently include: * synthesis * par @@ -34,46 +43,103 @@ The types of tools (by HAMMER names) supported currently include: * sram_generator * pcb -In order to configure your tool plugin of choice, you will need to set several configuration variables. -First, you should select which specific tool you want to use by setting ``vlsi.core._tool`` to the name of your tool. -For example ``vlsi.core.par_tool: "innovus"``. -You will also need to point hammer to the folder that contains your tool plugin by setting ``vlsi.core._tool_path``. -This directory should include a folder with the name of the tool as specified previously, which itself includes a python file ``__init__.py`` and a yaml file ``defaults.yml`` specifying the default values for any tool specific variables. -In addition you can also customize the version of the tools you use by setting ``..version`` to a tool specific string. -Looking at the tools ``defaults.yml`` will inform you if there are other variables you would like to set for your use of this tool. +Several configuration variables are needed to configure your tool plugin of choice. -The ``__init__.py`` file should contain a variable, ``tool``, that points to the class implementing this tools Hammer support. -This class should be a subclass of ``HammerTool``, which will be a subclass of ``HammerTool``. +First, select which tool to use for each action by setting ``vlsi.core._tool`` to the name of your tool, e.g. ``vlsi.core.par_tool: "innovus"``. + +Then, point Hammer to the folder that contains your tool plugin by setting ``vlsi.core._tool_path``. +This directory should include a folder with the name of the tool, which itself includes a python file ``__init__.py`` and a yaml file ``defaults.yml``. Customize the version of the tool by setting ``..version`` to a tool specific string. + +The ``__init__.py`` file should contain a variable, ``tool``, that points to the class implementing this tool. +This class should be a subclass of ``HammerTool``, which will be a subclass of ``HammerTool``. The class should implement methods for all the tool's steps. + +The ``defaults.yml`` file contains tool-specific configuration variables. The defaults may be overridden as necessary. Technology Plugins ================== -Hammer supports separately managed plugins for different technologies. You may be able to acquire access to certain pre-built technology plugins with permission from the technology vendor. Or, to build your own tech plugin, you need at least a ``.tech.json`` and ``defaults.yml``. An ``__init__.py`` is optional if there are any technology-specific methods or hooks to run. Refer to the ASAP7 plugin and associated documentation for more information. +Hammer supports separately managed technology plugins to satisfy NDAs. You may be able to acquire access to certain pre-built technology plugins with permission from the technology vendor. Or, to build your own tech plugin, you need at least a ``.tech.json`` and ``defaults.yml``. An ``__init__.py`` is optional if there are any technology-specific methods or hooks to run. -In order to configure your technology of choice, you will need to set several configuration variables. -First, you need to choose the technology, for example ``vlsi.core.technology: asap7`` and point to the location with the PDK tarball with ``technology..tarball_dir`` or pre-installed directory with ``technology..install_dir``. -Technology-specific options such as supplies, MMMC corners, metal layers, etc. will need to be matched to the technology in their respective ``vlsi.inputs...`` configurations. +The `ASAP7 plugin `__ is a good starting point for setting up a technology plugin. Refer to Hammer's documentation for the schema and setup instructions. -Configuration -============= +Several configuration variables are needed to configure your technology of choice. -To configure a hammer flow the user needs to supply a yaml or json configuration file the chooses the tool and technology plugins and versions as well as any design specific configuration APIs. +First, choose the technology, e.g. ``vlsi.core.technology: asap7``, then point to the location with the PDK tarball with ``technology..tarball_dir`` or pre-installed directory with ``technology..install_dir`` and (if applicable) the plugin repository with ``vlsi.core.technology_path``. -You can see the current set of all available Hammer APIs `here `__. +Technology-specific options such as supplies, MMMC corners, etc. are defined in their respective ``vlsi.inputs...`` configurations. Options for the most common use case are already defined in the technology's ``defaults.yml`` and can be overridden by the user. ASAP7 Tutorial ============== -The ``vlsi`` folder of this repository contains an example HAMMER flow with the SHA-3 accelerator and a dummy hard macro in the ASAP7 PDK. It is tested with the Cadence and Mentor tool plugins. +The ``vlsi`` folder of this repository contains an example HAMMER flow with the SHA-3 accelerator and a dummy hard macro in the ASAP7 PDK. It is intended for use with the Cadence and Mentor tool plugins. + +Project Structure +----------------- + +This example gives a suggested file structure and build system. The ``vlsi/`` folder will eventually contain the following files and folders: + +* Makefile + + * Integration of Hammer's build system into Chipyard and abstracts away some Hammer commands. + +* build + + * Hammer output directory. Can be changed with the ``OBJ_DIR`` variable. + * Will contain subdirectories such as ``syn-rundir`` and ``par-rundir`` and the ``inputs.yml`` denoting the top module and input Verilog files. + +* bwrc-env.yml + + * An example of tool environment configuration for BWRC affiliates. Replace as necessary for your environment. + +* example-vlsi + + * Entry point to Hammer. Contains example placeholders for hooks. + +* example.v + + * Verilog wrapper around the accelerator and dummy hard macro. + +* example.yml + + * Hammer IR for this tutorial. + +* extra_libraries + + * Contains collateral for the dummy hard macro. + +* generated-src + + * All of the elaborated Chisel and FIRRTL. + +* hammer, hammer--plugins, hammer--plugin + + * Core, tool, tech repositories. + +Prerequisites +------------- + +* Python 3.4+ +* numpy and gdspy packages +* Genus, Innovus, and Calibre licenses +* For ASAP7 specifically: + + * Download the `ASAP7 PDK `__ tarball and do not extract it + * If you have additional ASAP7 hard macros, their LEF & GDS need to be 4x upscaled @ 4000 DBU precision Initial Setup ------------- -Run ``./scripts/init-vlsi.sh TECH_HAME`` to pull the HAMMER & plugin submodules. Note that for technologies other than ASAP7, the tech submodule must be added in the ``vlsi`` folder first. +In the Chipyard root, run: -An example of tool environment configuration for BWRC affiliates is given in ``bwrc-env.yml``. Replace paths as necessary for your build environment. +.. code-block:: shell -Pull the HAMMER environment into the shell: + ``./scripts/init-vlsi.sh asap7`` + +to pull the HAMMER & plugin submodules. Note that for technologies other than ``asap7``, the tech submodule must be added in the ``vlsi`` folder first. -:: +Pull the Hammer environment into the shell: + +.. code-block:: shell + + cd vlsi export HAMMER_HOME=$PWD/hammer source $HAMMER_HOME/sourceme.sh @@ -81,42 +147,87 @@ Building the Design ------------------- To elaborate the Sha3RocketConfig (Rocketchip w/ the accelerator) and set up all prerequisites for the build system to push just the accelerator + hard macro through the flow: -:: - export MACROCOMPILER_MODE=' --mode synflops' +.. code-block:: shell + + export MACROCOMPILER_MODE='--mode synflops' export CONFIG=Sha3RocketConfig export VLSI_TOP=Sha3AccelwBB make buildfile -Note that because the ASAP7 process does not yet have a memory compiler, synflops are elaborated instead. +Note that because the ASAP7 process does not yet have a memory compiler, flip-flop arrays are used instead. + +For the curious, Hammer generates a set of Make targets in ``build/hammer.d``. ``make buildfile`` needs to be re-run if Make variables are changed. Running the VLSI Flow --------------------- -The configuration for this example is contained in ``example.yml`` and the entry script with placeholders for hooks is contained in ``example-vlsi``. Before continuing, ensure you have the `ASAP7 PDK `__ tarball downloaded (but not extracted) and point the ``technology.asap7.tarball_dir`` to the tarball directory. -To synthesize, type ``make syn``. +example-vlsi +^^^^^^^^^^^^ +This is the entry script with placeholders for hooks. In the ``ExampleDriver`` class, a list of hooks is passed in the ``get_extra_par_hooks``. Hooks are additional snippets of python and TCL (via ``x.append()``) to extend the Hammer APIs. Hooks can be inserted using the ``make_pre/post/replacement_hook`` methods. -Post-synthesis results are in ``build/syn-rundir``. Raw QoR data is available at ``build/syn-rundir/reports``, and methods to extract this information for design space exploration are a WIP. +example.yml +^^^^^^^^^^^ +This contains the Hammer configuration for this example project. Example clock constraints, power straps definitions, placement constraints, and pin constraints are given. Additional configuration for the extra libraries and tools are at the bottom. -To place and route, type ``make par``. +First, set ``technology.asap7.tarball_dir`` to where you downloaded the ASAP7 PDK. -If successful, the resulting chip can be opened via ``./build/par-rundir/generated-scripts/open_chip``. +Synthesis +^^^^^^^^^ +.. code-block:: shell -Intermediate database are written in ``build/par-rundir`` between each step of the ``par`` action, and can be restored in an interactive Innovus session as desired for debugging purposes. Compressed timing reports are found in ``build/par-rundir/timingReports``. + ``make syn`` -To run DRC & LVS, and view the results: +Post-synthesis logs and collateral are in ``build/syn-rundir``. The Raw QoR data is available at ``build/syn-rundir/reports``, and methods to extract this information for design space exploration are a WIP. + +Place-and-Route +^^^^^^^^^^^^^^^ +.. code-block:: shell + + ``make par`` + +After completion, the final database can be opened in an interactive Innovus session via ``./build/par-rundir/generated-scripts/open_chip``. + +Intermediate database are written in ``build/par-rundir`` between each step of the ``par`` action, and can be restored in an interactive Innovus session as desired for debugging purposes. + +Timing reports are found in ``build/par-rundir/timingReports``. They are gzipped text files. + +DRC & LVS +^^^^^^^^^ +To run DRC & LVS, and view the results in Calibre: + +.. code-block:: shell -:: make drc ./build/drc-rundir/generated-scripts/view-drc make lvs ./build/lvs-rundir/generated-scripts/view-lvs -Some DRC errors are expected from this PDK, as explained in the `ASAP7 plugin readme `__ +Some DRC errors are expected from this PDK, as explained in the `ASAP7 plugin readme `__. + +Advanced Usage +============== Alternative RTL Flows --------------------- -The Make-based build system provided supports using HAMMER without using RTL generated by Chipyard. To push a custom verilog module through, one only needs to export the following environment variables before ``make buildfile``. +The Make-based build system provided supports using Hammer without using RTL generated by Chipyard. To push a custom verilog module through, one only needs to export the following environment variables before ``make buildfile``. + +.. code-block:: shell -:: export CUSTOM_VLOG= export VLSI_TOP= + +Manual Step Execution & Dependency Tracking +------------------------------------------- +It is invariably necessary to debug certain steps of the flow, e.g. if the power strap settings need to be updated. The underlying Hammer commands support options such as ``--to_step``, ``--from_step``, and ``--only_step``. These allow you to control which steps of a particular action are executed. + +Make's dependency tracking can sometimes result in re-starting the entire flow when the user only wants to re-run a certain action. Hammer's build system has "redo" targets such as ``redo-syn`` and ``redo-par``. + +Say you need to update some power straps settings in ``example.yml`` and want to try out the new settings: + +.. code-block:: shell + + make redo-par HAMMER_REDO_ARGS='-p example.yml --only_step power_straps' + +Simulation +---------- +With the Synopsys plugin, RTL and gate-level simulation is supported using VCS. While this example does not implement any simulation, refer to Hammer's documentation for how to set it up for your design. diff --git a/vlsi/example.yml b/vlsi/example.yml index f68bbd12..e641f8c2 100644 --- a/vlsi/example.yml +++ b/vlsi/example.yml @@ -2,24 +2,16 @@ # Technology used is ASAP7 vlsi.core.technology: asap7 # Specify dir with ASAP7 tarball -technology.asap7.tarball_dir: "SPECIFY DIR WITH ASAP7 TARBALL" +technology.asap7.tarball_dir: "" vlsi.core.max_threads: 12 # General Hammer Inputs -vlsi.inputs.supplies.VDD: "0.7 V" - # Hammer will auto-generate a CPF for simple power designs; see hammer/src/hammer-vlsi/defaults.yml for more info vlsi.inputs.power_spec_mode: "auto" vlsi.inputs.power_spec_type: "cpf" -# Specify the setup and hold corners for ASAP7 -vlsi.inputs.mmmc_corners: [ - {name: "PVT_0P63V_100C", type: "setup", voltage: "0.63 V", temp: "100 C"}, - {name: "PVT_0P77V_0C", type: "hold", voltage: "0.77 V", temp: "0 C"} -] - # Specify clock signals vlsi.inputs.clocks: [ {name: "clock", period: "1ns", uncertainty: "0.1ns"} @@ -50,9 +42,10 @@ par.generate_power_straps_options: power_utilization_M9: 1.0 # Placement Constraints +# For ASAP7, all numbers must be 4x larger than final GDS vlsi.inputs.placement_constraints: - path: "Sha3AccelwBB" - type: "toplevel" + type: toplevel x: 0 y: 0 width: 300 @@ -63,12 +56,13 @@ vlsi.inputs.placement_constraints: top: 0 bottom: 1.08 #must be at least this number - path: "Sha3AccelwBB/dco" - type: "hardmacro" - x: 100 - y: 100 - width: 32 - height: 32 - orientation: "r0" + type: hardmacro + x: 108 + y: 108 + width: 128 + height: 128 + orientation: r0 + top_layer: M9 # Pin placement constraints vlsi.inputs.pin_mode: generated @@ -116,7 +110,8 @@ par.inputs.physical_only_cells_list: # SRAM Compiler compiler options vlsi.core.sram_generator_tool: "sram_compiler" -vlsi.core.sram_generator_tool_path: ["SPECIFY LOCATION OF SRAM GENERATOR IN TECH PLUGIN"] +# You should specify a location for the SRAM generator in the tech plugin +vlsi.core.sram_generator_tool_path: [] vlsi.core.sram_generator_tool_path_meta: "append" # Tool options. Replace with your tool plugin of choice. @@ -124,12 +119,12 @@ vlsi.core.sram_generator_tool_path_meta: "append" vlsi.core.synthesis_tool: "genus" vlsi.core.synthesis_tool_path: ["hammer-cadence-plugins/synthesis"] vlsi.core.synthesis_tool_path_meta: "append" -synthesis.genus.version: "181" +synthesis.genus.version: "1813" # Innovus options vlsi.core.par_tool: "innovus" vlsi.core.par_tool_path: ["hammer-cadence-plugins/par"] vlsi.core.par_tool_path_meta: "append" -par.innovus.version: "181" +par.innovus.version: "191" par.innovus.design_flow_effort: "standard" par.inputs.gds_merge: true # Calibre options diff --git a/vlsi/extra_libraries/dco/ExampleDCO.gds b/vlsi/extra_libraries/dco/ExampleDCO.gds index 843e5dffde0888fed5ae34c73a086f90c1f56936..e60564bc3734d73f354e96ff65b354214ddee5f4 100644 GIT binary patch delta 813 zcmZ{i&1(};6va=b=}UuYn3P&F$)ss%Kq-|<{pd$pX{HGji})Z?f&pWjj3ADt*oD$A znys!z@6wI95!}^<=u!|7bTRk`xbYw8!j&tN`(6eOxOi~5_jk`b_whQibM*)UhEanZ zF=9UvM;a+CA@{e2X$bf6&iy^lJ=bcsf$^c?E2SrkTc2N_ESKNUzkG4?2JGSg&nJbb zsQL27bwo!1F>2r}MAE?V(Y>^o>HvpBbdp|<;V=PIT6Er8O~tpJ!HC#Z7WDn=DTS4%mnNpo2RjGJ_z8v)4l3NUq40t-ddPu#3EV#ixTA^+}w7K54mbQnH|`Ym#bOuK4t-u#rW5 Wz55dr7_r25wF*R2-4pAcDE9(E7>2)7+6%&1ia=q2D9WFSPzx$hF=m9)xDY8J@uy%~+Ky-_whkCjBx%GS zRtgdq{76`!*p-T|RFoyMBBCyp1q*-Jm{d2K=y&gV-_G@V^TnQ7xRAT(GkK@ackbLd zbG~zDB$7I5ka@07_Q(zTxJho2#?<5K(o`3f_io!cG*DjF-!~{SV?x9IO}!hw`eo#g zwrMR>epvkNTQaYq>d%#hDZfz~qiDVN+t+QB`bi?ujdgOnM2&UwyDV**Ant09xEYtk zjY^fxojxb^`TA*+>x&+4{;d3`fc#ZHSkHzO}`yJ*#V!_-1IlXCpW<-H8=e(_~cgjq~@kyhEHyXPik)Z zL-5H8d{T4M-v^)E51-WB^k0Qf9)wS7Zu*DelSkl_nw$O!_~c3Wq~@l720l3gpVZv+ z&%!4^hEHm4`sd)2U%)3dH~kCn$&2tw%}xI@eDWLkq~@0IKJoq-Kl8pL^?B2OA3pgZ zd{T4MKMkLJ7e1-E=^uqp9*0kAZu+moClA3VH8=eO@X1%;lbW0UUijn-@JY>0e`!!Yq~@moD17p9_@w5h{}6ogVfduxrvCtZavgk9bJJf5pIi-} z)ZFy%fKM)iPik)ZGvSl7;FFr0{$%)M0Y0g@<;$PmC!K>2#<}T_!Y6<8zL1)m{*Um< zpW&05oBnt3$t&W8hwBLrN;XQ?~5K|eV2WheV5GbzbT)6mt@~1HBZmq^!X>_pC0z} zon+r7H8*|sU6Os5%_3J&GFfHN%mb*bJJ(vCE0gL%}t+umt@~1bNg@V z^|SAi?7O7q=J@QpB>OIz+kaEzv+t7ZyJT+vP5JD*B>OI@xq1HVyCnNAncII;nGO=@oX?As*!HmSMgvu~6Cu76jrpRjL}?AxT~=J@Q} zB>Oh0x#_cSlUKwaq~@l7c{o|Wgyek>sk!N2fKOiZ!wado>7Rp7^1hGM-1N`FCwbpV zYHs>x;FBXbe^PVPKLMXS37^#5^bf-)kH9B2H+_EZKpuooYHs@bFh02-KB>9s55XrZ z@JY>0pWpkC+u@U%n|>F@C%3{UH8=f@@X1Z^NzF~a9X{CspVZv++u)OH;FFr0ehYlE z6+WrC=`Vm!E`m>LZu+y~lXKvcnx}ogf5!T`xa9wN$@wa$o)U?3QlI&!@4tUe{x3Gi z;rso!AK&db@4u^lrc~vq?kVG(yxQ}(@zcHxdtVNCKcRX_PUiYJ|NqzzdHwy#{y)|K z^yRwI`uJT)7+*L4*fai{ynhA%`@s~6n(H)+W;y-+BAVm$aba#lsdzL#j!9u&!`iM` z(xafiG000=_gXFO{c@&G;QQ~M&(sN=k4|@tx}H^ESK#Nv z^=0Y=eqP;UnL2^%hue^;6S$tawV67B>#JLpsS~)~yQP^rf&IrdC!dVe9xk-^yD8a9 z!7GSlD}}Bg@@uwI=n5h~Wh;fOAZ};8_is)1{+l;ruRKxdZ#R;AgzJB Date: Wed, 25 Sep 2019 17:54:47 -0700 Subject: [PATCH 19/39] extra cleanup [ci skip] --- docs/Customization/Firrtl-Transforms.rst | 65 ++++++++++++------- docs/Tools/FIRRTL.rst | 1 + .../src/main/scala/TargetMixins.scala | 2 - 3 files changed, 41 insertions(+), 27 deletions(-) diff --git a/docs/Customization/Firrtl-Transforms.rst b/docs/Customization/Firrtl-Transforms.rst index 4d947522..64aba247 100644 --- a/docs/Customization/Firrtl-Transforms.rst +++ b/docs/Customization/Firrtl-Transforms.rst @@ -3,14 +3,16 @@ Adding a Firrtl Transform ========================= -After writing the Chisel RTL, you can make further modifications by adding transforms during the FIRRTL compilation phase. -As mentioned in Section <>, transforms are modifications that happen on the FIRRTL IR that can modify a circuit. -Transforms are a powerful tool to take in the FIRRTL IR that is emitted from Chisel and run analysis (https://www.youtube.com/watch?v=FktjrjRVBoY) or convert the circuit into a new form. +Similar to how LLVM IR passes can perform transformations and optimizations on software, FIRRTL transforms can +modify Chisel-elaborated RTL. +As mentioned in Section :ref:`firrtl`, transforms are modifications that happen on the FIRRTL IR that can modify a circuit. +Transforms are a powerful tool to take in the FIRRTL IR that is emitted from Chisel and run analysis or convert the circuit into a new form. Where to add transforms ----------------------- -In Chipyard, the FIRRTL compiler is called multiple times to create a "Top" file that has the DUT and a "Harness" file that has all harness collateral. +In Chipyard, the FIRRTL compiler is called multiple times to create a "Top" file that contains the DUT and a "Harness" file containing the test harness, which instantiates the DUT. +The "Harness" file does not contain the DUT's module definition or any of its submodules. This done by the ``tapeout`` SBT project (located in ``tools/barstools/tapeout``) which calls ``GenerateTopAndHarness`` (a function that wraps the multiple FIRRTL compiler calls and extra transforms). .. literalinclude:: ../../common.mk @@ -19,7 +21,7 @@ This done by the ``tapeout`` SBT project (located in ``tools/barstools/tapeout`` :end-before: DOC include end: FirrtlCompiler If you look inside of the `tools/barstools/tapeout/src/main/scala/transforms/Generate.scala `__ file, -you can see that FIRRTL invoked twice, once for the "Top" and once for the "Harness". If you want to add transforms to just modify the DUT, you can add them to ``topTransforms``. +you can see that FIRRTL is invoked twice, once for the "Top" and once for the "Harness". If you want to add transforms to just modify the DUT, you can add them to ``topTransforms``. Otherwise, if you want to add transforms to just modify the test harness, you can add them to ``harnessTransforms``. Examples of transforms @@ -31,38 +33,51 @@ This includes transforms that can flatten modules (``Flatten``), group modules t Transforms can be standalone or can take annotations as input. Annotations are used to pass information between FIRRTL transforms. This includes information on what modules to flatten, group, and more. Annotations can be added to the code by -adding them to your Chisel source or by creating the ``.json`` file and adding it to the FIRRTL compiler (note: adding to the Chisel source will add the ``json`` snippet into the build system for you). -**The recommended way to annotate something is to do it in the Chisel source**. +adding them to your Chisel source or by creating a serialized annotation ``json`` file and adding it to the FIRRTL compiler +(note: annotating the Chisel source will automatically serialize the annotation as a ``json`` snippet into the build system for you). +**The recommended way to annotate something is to do it in the Chisel source, but not all annotation types have Chisel APIs**. -Here is an example of adding an annotation within the Chisel source. This example is taken from the -``firechip`` project and uses an annotation to mark BOOM's register file for optimization: +Here is an example of adding a ``DontTouchAnnotation`` within the Chisel source. This annotation +makes sure that a particular signal is not removed by the "Dead Code Elimination" pass in FIRRTL: -.. literalinclude:: ../../generators/firechip/src/main/scala/TargetMixins.scala - :language: make - :start-after: DOC include start: ChiselAnnotation - :end-before: DOC include end: ChiselAnnotation +.. code-block:: scala -Here is an example of grouping a series of modules by specifying the ``.json`` file. + class TopModule extends Module { + ... + val submod = Module(new Submodule) + ... + } + + class Submodule extends Module { + ... + val some_signal := ... + annotate(new ChiselAnnotation { + def toFirrtl = DontTouchAnnotation(some_signal.toNamed) + }) + + // or use the wrapper for this + // chisel3.experimental.dontTouch(some_signal) + ... + } + +Here is an example of the ``DontTouchAnnotation`` when it is serialized: .. code-block:: json [ { - "class": "firrtl.transforms.GroupAnnotation", - "components": [ - "BeagleChipTop.BeagleChipTop.instance1", - "BeagleChipTop.BeagleChipTop.instance2", - ], - "newModule": "NewModule", - "newInstance": "newModInst" + "class": "firrtl.transforms.DontTouchAnnotation", + "target": "~TopModule|Submodule>some_signal" } ] -In this case, the specific syntax depends on the type of annotation. The best way to figure out -what the ``json`` file should contain is to first try to annotate in the Chisel -source and then see what the ``json`` output gives and copy that format. +In this case, the specific syntax depends on the type of annotation and its fields. +One of the easier ways to figure out the serialized syntax is to first try and find a Chisel +annotation to add to the code. Then you can look at the collateral that is generated from the +build system, find the ``*.anno.json``, and find the proper syntax for the annotation. -Once ``yourAnnoFile.json`` is created then you can add ``-faf yourAnnoFile.json`` to the FIRRTL compiler invocation in ``common.mk``. +Once ``yourAnnoFile.json`` is created then you can add ``-faf yourAnnoFile.json`` to the FIRRTL +compiler invocation in ``common.mk``. .. literalinclude:: ../../common.mk :language: make diff --git a/docs/Tools/FIRRTL.rst b/docs/Tools/FIRRTL.rst index 23f39f16..b850b39e 100644 --- a/docs/Tools/FIRRTL.rst +++ b/docs/Tools/FIRRTL.rst @@ -1,3 +1,4 @@ +.. _firrtl: FIRRTL ================================ diff --git a/generators/firechip/src/main/scala/TargetMixins.scala b/generators/firechip/src/main/scala/TargetMixins.scala index 9a8dd739..f36cf021 100644 --- a/generators/firechip/src/main/scala/TargetMixins.scala +++ b/generators/firechip/src/main/scala/TargetMixins.scala @@ -108,7 +108,6 @@ trait ExcludeInvalidBoomAssertions extends LazyModuleImp { trait CanHaveMultiCycleRegfileImp { val outer: utilities.HasBoomAndRocketTiles val boomCores = outer.boomTiles.map(tile => tile.module.core) - // DOC include start: ChiselAnnotation boomCores.foreach({ core => core.iregfile match { case irf: boom.exu.RegisterFileSynthesizable => annotate(MemModelAnnotation(irf.regfile)) @@ -120,7 +119,6 @@ trait CanHaveMultiCycleRegfileImp { case _ => Nil } }) - // DOC include end: ChiselAnnotation outer.rocketTiles.foreach({ tile => annotate(MemModelAnnotation(tile.module.core.rocketImpl.rf.rf)) From c2ce173195a03868c5a33fc40129b35e31d41d0f Mon Sep 17 00:00:00 2001 From: Albert Magyar Date: Wed, 25 Sep 2019 19:32:34 -0700 Subject: [PATCH 20/39] Add Verilog MMIO GCD peripheral example --- build.sbt | 2 +- .../Incorporating-Verilog-Blocks.rst | 156 ++++++++++++++++++ docs/Customization/index.rst | 1 + .../src/main/resources/vsrc/GCDMMIOBlackBox.v | 48 ++++++ .../example/src/main/scala/ConfigMixins.scala | 8 + .../src/main/scala/GCDMMIOBlackBox.scala | 98 +++++++++++ .../src/main/scala/RocketConfigs.scala | 7 + generators/example/src/main/scala/Top.scala | 10 ++ tests/gcd.c | 42 +++++ 9 files changed, 371 insertions(+), 1 deletion(-) create mode 100644 docs/Customization/Incorporating-Verilog-Blocks.rst create mode 100644 generators/example/src/main/resources/vsrc/GCDMMIOBlackBox.v create mode 100644 generators/example/src/main/scala/GCDMMIOBlackBox.scala create mode 100644 tests/gcd.c diff --git a/build.sbt b/build.sbt index 8083dc3d..05a80bba 100644 --- a/build.sbt +++ b/build.sbt @@ -147,7 +147,7 @@ lazy val sha3 = (project in file("generators/sha3")) .settings(commonSettings) lazy val tapeout = conditionalDependsOn(project in file("./tools/barstools/tapeout/")) - .dependsOn(chisel_testers) + .dependsOn(chisel_testers, example) .settings(commonSettings) lazy val mdf = (project in file("./tools/barstools/mdf/scalalib/")) diff --git a/docs/Customization/Incorporating-Verilog-Blocks.rst b/docs/Customization/Incorporating-Verilog-Blocks.rst new file mode 100644 index 00000000..424b4c7e --- /dev/null +++ b/docs/Customization/Incorporating-Verilog-Blocks.rst @@ -0,0 +1,156 @@ +.. _incorporating-verilog-blocks: + +Incorporating Verilog Blocks +============================ + +Working with existing Verilog IP is an integral part of many chip +design flows. Fortunately, both Chisel and Chipyard provide extensive +support for Verilog integration. + +Here, we will examine the process of incorporating an MMIO peripheral +(similar to the PWM example from the previous section) that uses a +Verilog implementation of Greatest Common Denominator (GCD) +algorithm. There are a few steps to adding a Verilog peripheral: + +* Adding a Verilog resource file to the project +* Defining a Chisel ``BlackBox`` representing the Verilog module +* Instantiating the ``BlackBox`` and interfacing ``RegField`` entries +* Setting up a chip ``Top`` and ``Config`` that use the peripheral + +Adding a Verilog blackbox resource file +--------------------------------------- + +As before, it is possible to incorporate peripherals as part of your +own generator project. However, Verilog resource files must go in a +different directory from Chisel (Scala) sources. + +.. code-block:: none + + generators/yourproject/ + build.sbt + src/main/ + scala/ + resources/ + vsrc/ + YourFile.v + +In addition to the steps outlined in the previous section on adding a +project to the ``build.sbt`` at the top level, it is also necessary to +add any projects that contain Verilog IP as dependencies to the +``tapeout`` project. + +.. code-block:: scala + + lazy val tapeout = conditionalDependsOn(project in file("./tools/barstools/tapeout/")) + .dependsOn(chisel_testers, example, yourproject) + .settings(commonSettings) + +For this concrete GCD example, we will be using a ``GCDMMIOBlackBox`` +Verilog module that is defined in the ``example`` project. The Scala +and Verilog sources follow the prescribed directory layout. + +.. code-block:: none + + generators/example/ + build.sbt + src/main/ + scala/ + GCDMMIOBlackBox.scala + resources/ + vsrc/ + GCDMMIOBlackBox.v + +Defining a Chisel BlackBox +-------------------------- + +A Chisel ``BlackBox`` module provides a way of instantiating a module +defined by an external Verilog source. The definition of the blackbox +includes several aspects that allow it to be translated to an instance +of the Verilog module: + +* An ``io`` field: a bundle with fields corresponding to the portlist of the Verilog module. +* A constructor parameter that takes a ``Map`` from Verilog parameter name to elaborated value +* One or more resources added to indicate Verilog source dependencies + +Of particular interest is the fact that parameterized Verilog modules +can be passed the full space of possible parameter values. These +values may depend on elaboration-time values in the Chisel generator, +as the bitwidth of the GCD calculation does in this example. + +**Verilog GCD port list and parameters** + +.. literalinclude:: ../../generators/example/src/main/resources/vsrc/GCDMMIOBlackBox.v + :language: verilog + :start-after: DOC include start: GCD portlist + :end-before: DOC include end: GCD portlist + +**Chisel BlackBox Definition** + +.. literalinclude:: ../../generators/example/src/main/scala/GCDMMIOBlackBox.scala + :language: scala + :start-after: DOC include start: GCD blackbox + :end-before: DOC include end: GCD blackbox + +Instantiating the BlackBox and Defining MMIO +-------------------------------------------- + +Next, we must instantiate the blackbox. In order to take advantage of +diplomatic memory mapping on the system bus, we still have to +integrate the peripheral at the Chisel level by mixing +peripheral-specific traits into a ``TLRegisterRouter``. The ``params`` +member and ``HasRegMap`` base trait should look familiar from the +previous memory-mapped PWM device example. + +.. literalinclude:: ../../generators/example/src/main/scala/GCDMMIOBlackBox.scala + :language: scala + :start-after: DOC include start: GCD instance regmap + :end-before: DOC include end: GCD instance regmap + +Advanced Features of RegField Entries +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +One signficant difference from the PWM example is in the peripheral's +memory map. ``RegField`` exposes polymorphic ``r`` and ``w`` methods +that allow read- and write-only memory-mapped registers to be +interfaced to hardware in multiple ways. + +* ``RegField.r(2, status)`` is used to create a 2-bit, read-only register that captures the current value of the ``status`` signal when read. +* ``RegField.r(params.width, gcd)`` "connects" the decoupled handshaking interface ``gcd`` to a read-only memory-mapped register. When this register is read via MMIO, the ``ready`` signal is asserted. This is in turn connected to ``output_ready`` on the Verilog blackbox through the glue logic. +* ``RegField.w(params.width, x)`` exposes a plain register (much like those in the PWM example) via MMIO, but makes it write-only. +* ``RegField.w(params.width, y)`` associates the decoupled interface signal ``y`` with a write-only memory-mapped register, causing ``y.valid`` to be asserted when the register is written. + +Since the ready/valid signals of ``y`` are connected to the +``input_ready`` and ``input_valid`` signals of the blackbox, +respectively, this register map and glue logic has the effect of +triggering the GCD algorithm when ``y`` is written. Therefore, the +algorithm is set up by first writing ``x`` and then performing a +triggering write to ``y``. Polling can be used for status checks. + +Defining a Chip with a GCD Peripheral +--------------------------------------- + +As with the PWM example, a few more pieces are needed to tie the system together. + +**Composing traits into a complete cake pattern peripheral** + +.. literalinclude:: ../../generators/example/src/main/scala/GCDMMIOBlackBox.scala + :language: scala + :start-after: DOC include start: GCD cake + :end-before: DOC include end: GCD cake + +Note the differences arising due to the fact that this peripheral has +no top-level IO. To build a complete system, a new ``Top`` and new +``Config`` objects are added in a manner exactly analogous to the PWM +example. + +Software Testing +---------------- + +The GCD module has a slightly more complex interface, so polling is +used to check the status of the device before each triggering read or +write. + +.. literalinclude:: ../../tests/gcd.c + :language: scala + :start-after: DOC include start: GCD test + :end-before: DOC include end: GCD test diff --git a/docs/Customization/index.rst b/docs/Customization/index.rst index c0432e73..73d68068 100644 --- a/docs/Customization/index.rst +++ b/docs/Customization/index.rst @@ -15,5 +15,6 @@ Hit next to get started! Heterogeneous-SoCs Adding-An-Accelerator + Incorporating-Verilog-Blocks Memory-Hierarchy Boot-Process diff --git a/generators/example/src/main/resources/vsrc/GCDMMIOBlackBox.v b/generators/example/src/main/resources/vsrc/GCDMMIOBlackBox.v new file mode 100644 index 00000000..9104ae87 --- /dev/null +++ b/generators/example/src/main/resources/vsrc/GCDMMIOBlackBox.v @@ -0,0 +1,48 @@ +// DOC include start: GCD portlist +module GCDMMIOBlackBox + #(parameter WIDTH) + ( + input clock, + input reset, + output input_ready, + input input_valid, + input [WIDTH-1:0] x, + input [WIDTH-1:0] y, + input output_ready, + output output_valid, + output reg [WIDTH-1:0] gcd + ); +// DOC include end: GCD portlist + + localparam S_IDLE = 2'b00, S_RUN = 2'b01, S_DONE = 2'b10; + + reg [1:0] state; + reg [WIDTH-1:0] tmp; + + assign input_ready = state == S_IDLE; + assign output_valid = state == S_DONE; + + always @(posedge clock) begin + if (reset) + state <= S_IDLE; + else if (state == S_IDLE && input_valid) + state <= S_RUN; + else if (state == S_RUN && tmp == 0) + state <= S_DONE; + else if (state == S_DONE && output_ready) + state <= S_IDLE; + end + + always @(posedge clock) begin + if (state == S_IDLE && input_valid) begin + gcd <= x; + tmp <= y; + end else if (state == S_RUN) begin + if (gcd > tmp) + gcd <= gcd - tmp; + else + tmp <= tmp - gcd; + end + end + +endmodule // GCDMMIOBlackBox diff --git a/generators/example/src/main/scala/ConfigMixins.scala b/generators/example/src/main/scala/ConfigMixins.scala index 9d92d896..7d7e74af 100644 --- a/generators/example/src/main/scala/ConfigMixins.scala +++ b/generators/example/src/main/scala/ConfigMixins.scala @@ -87,6 +87,14 @@ class WithPWMAXI4Top extends Config((site, here, up) => { Module(LazyModule(new TopWithPWMAXI4()(p)).module) }) +/** + * Class to specify a top level BOOM and/or Rocket system with a TL-attached GCD device + */ +class WithGCDTop extends Config((site, here, up) => { + case BuildTop => (clock: Clock, reset: Bool, p: Parameters) => + Module(LazyModule(new TopWithGCD()(p)).module) +}) + /** * Class to specify a top level BOOM and/or Rocket system with a block device */ diff --git a/generators/example/src/main/scala/GCDMMIOBlackBox.scala b/generators/example/src/main/scala/GCDMMIOBlackBox.scala new file mode 100644 index 00000000..891fe1c9 --- /dev/null +++ b/generators/example/src/main/scala/GCDMMIOBlackBox.scala @@ -0,0 +1,98 @@ +package example + +import chisel3._ +import chisel3.util._ +import chisel3.core.{IntParam, Reset} +import freechips.rocketchip.amba.axi4._ +import freechips.rocketchip.subsystem.BaseSubsystem +import freechips.rocketchip.config.{Parameters, Field} +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.regmapper.{HasRegMap, RegField} +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.util.UIntIsOneOf + +// DOC include start: GCD blackbox +class GCDMMIOBlackBox(w: Int) extends BlackBox(Map("WIDTH" -> IntParam(w))) with HasBlackBoxResource { + val io = IO(new Bundle { + val clock = Input(Clock()) + val reset = Input(Bool()) + val input_ready = Output(Bool()) + val input_valid = Input(Bool()) + val x = Input(UInt(w.W)) + val y = Input(UInt(w.W)) + val output_ready = Input(Bool()) + val output_valid = Output(Bool()) + val gcd = Output(UInt(w.W)) + }) + + addResource("/vsrc/GCDMMIOBlackBox.v") +} +// DOC include end: GCD blackbox + +// DOC include start: GCD instance regmap +case class GCDParams(address: BigInt, beatBytes: Int, width: Int) + +trait GCDModule extends HasRegMap { + implicit val p: Parameters + def params: GCDParams + val clock: Clock + val reset: Reset + + val impl = Module(new GCDMMIOBlackBox(params.width)) + + // How many clock cycles in a PWM cycle? + val x = Reg(UInt(params.width.W)) + val y = Wire(new DecoupledIO(impl.io.y)) + val gcd = Wire(new DecoupledIO(impl.io.gcd)) + val status = Cat(impl.io.input_ready, impl.io.output_valid) + + impl.io.clock := clock + impl.io.reset := reset.asBool + impl.io.x := x + impl.io.y := y.bits + impl.io.input_valid := y.valid + y.ready := impl.io.input_ready + + gcd.bits := impl.io.gcd + gcd.valid := impl.io.output_valid + impl.io.output_ready := gcd.ready + + regmap( + 0x00 -> Seq( + RegField.r(2, status)), // a read-only register capturing current status + 0x04 -> Seq( + RegField.w(params.width, x)), // a plain, write-only register + 0x08 -> Seq( + RegField.w(params.width, y)), // write-only, y.valid is set on write + 0x0C -> Seq( + RegField.r(params.width, gcd))) // read-only, gcd.ready is set on read +} +// DOC include end: GCD instance regmap + +// DOC include start: GCD cake +class GCD(c: GCDParams)(implicit p: Parameters) + extends TLRegisterRouter( + c.address, "gcd", Seq("ucbbar,gcd"), + beatBytes = c.beatBytes)( + new TLRegBundle(c, _))( + new TLRegModule(c, _, _) with GCDModule) + +trait HasPeripheryGCD { this: BaseSubsystem => + implicit val p: Parameters + + private val address = 0x2000 + private val portName = "gcd" + private val gcdWidth = 32 + + val gcd = LazyModule(new GCD( + GCDParams(address, pbus.beatBytes, gcdWidth))(p)) + + pbus.toVariableWidthSlave(Some(portName)) { gcd.node } +} + +trait HasPeripheryGCDModuleImp extends LazyModuleImp { + implicit val p: Parameters + val outer: HasPeripheryGCD +} + +// DOC include end: GCD cake diff --git a/generators/example/src/main/scala/RocketConfigs.scala b/generators/example/src/main/scala/RocketConfigs.scala index 0acf7284..5384240e 100644 --- a/generators/example/src/main/scala/RocketConfigs.scala +++ b/generators/example/src/main/scala/RocketConfigs.scala @@ -57,6 +57,13 @@ class PWMAXI4RocketConfig extends Config( new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.system.BaseConfig) +class GCDRocketConfig extends Config( // add MMIO GCD module + new WithGCDTop ++ + new WithBootROM ++ + new freechips.rocketchip.subsystem.WithInclusiveCache ++ + new freechips.rocketchip.subsystem.WithNBigCores(1) ++ + new freechips.rocketchip.system.BaseConfig) + class SimBlockDeviceRocketConfig extends Config( new testchipip.WithBlockDevice ++ // add block-device module to peripherybus new WithSimBlockDeviceTop ++ // use top with block-device IOs and connect to simblockdevice diff --git a/generators/example/src/main/scala/Top.scala b/generators/example/src/main/scala/Top.scala index 94bed0de..b7f1a500 100644 --- a/generators/example/src/main/scala/Top.scala +++ b/generators/example/src/main/scala/Top.scala @@ -53,6 +53,16 @@ class TopWithPWMAXI4Module(l: TopWithPWMAXI4) extends TopModule(l) //--------------------------------------------------------------------------------------------------------- +class TopWithGCD(implicit p: Parameters) extends Top + with HasPeripheryGCD { + override lazy val module = new TopWithGCDModule(this) +} + +class TopWithGCDModule(l: TopWithGCD) extends TopModule(l) + with HasPeripheryGCDModuleImp + +//--------------------------------------------------------------------------------------------------------- + class TopWithBlockDevice(implicit p: Parameters) extends Top with HasPeripheryBlockDevice { override lazy val module = new TopWithBlockDeviceModule(this) diff --git a/tests/gcd.c b/tests/gcd.c new file mode 100644 index 00000000..a89abf65 --- /dev/null +++ b/tests/gcd.c @@ -0,0 +1,42 @@ +#include "mmio.h" + +#define GCD_STATUS 0x2000 +#define GCD_X 0x2004 +#define GCD_Y 0x2008 +#define GCD_GCD 0x200C + +unsigned int gcd_ref(unsigned int x, unsigned int y) { + while (y != 0) { + if (x > y) + x = x - y; + else + y = y - x; + } + return x; +} + +// DOC include start: GCD test +int main(void) +{ + uint32_t result, ref, x = 20, y = 15; + + // wait for peripheral to be ready + while ((reg_read8(GCD_STATUS) & 0x2) == 0) ; + + reg_write32(GCD_X, x); + reg_write32(GCD_Y, y); + + + // wait for peripheral to complete + while ((reg_read8(GCD_STATUS) & 0x1) == 0) ; + + result = reg_read32(GCD_GCD); + ref = gcd_ref(x, y); + + if (result != ref) { + printf("Hardware result %d does not match reference value %d\n", result, ref); + return 1; + } + return 0; +} +// DOC include end: GCD test From 216ae3ee548918c518f1a2fa570cdf930866c0cd Mon Sep 17 00:00:00 2001 From: Albert Magyar Date: Thu, 26 Sep 2019 09:32:38 -0700 Subject: [PATCH 21/39] Add more tips for Verilog blackbox integration --- .../Incorporating-Verilog-Blocks.rst | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/docs/Customization/Incorporating-Verilog-Blocks.rst b/docs/Customization/Incorporating-Verilog-Blocks.rst index 424b4c7e..2052eec6 100644 --- a/docs/Customization/Incorporating-Verilog-Blocks.rst +++ b/docs/Customization/Incorporating-Verilog-Blocks.rst @@ -37,7 +37,10 @@ different directory from Chisel (Scala) sources. In addition to the steps outlined in the previous section on adding a project to the ``build.sbt`` at the top level, it is also necessary to add any projects that contain Verilog IP as dependencies to the -``tapeout`` project. +``tapeout`` project. This ensures that the Verilog sources are visible +to the downstream FIRRTL passes that provide utilities for integrating +Verilog files into the build process, which are part of the +``tapeout`` package in ``barstools/tapeout``. .. code-block:: scala @@ -154,3 +157,25 @@ write. :language: scala :start-after: DOC include start: GCD test :end-before: DOC include end: GCD test + +Support for Verilog in Downstream Berkeley Tools +------------------------------------------------ + +There are important differences in how Verilog blackboxes are treated +by downstream tools. Since they remain blackboxes in FIRRTL, their +ability to be processed by FIRRTL transforms is limited, and some +advanced features of Chipyard may provide weaker support for +blackboxes. Note that the remainder of the target design may still +generally be transformed or augmented by any Chipyard FIRRTL +transform. + +* Verilog blackboxes are fully supported for generating tapeout-ready RTL +* HAMMER workflows offer robust support for integrating Verilog blackboxes +* FireSim relies on FIRRTL transformations to generate a decoupled + FPGA simulator. Therefore, support for Verilog blackboxes in FireSim + is currently limited but rapidly evolving. Stay tuned! + +As mentioned earlier in this section, ``BlackBox`` resource files must +be integrated into the build process, so any project providing +``BlackBox`` resources must be made visible to the ``tapeout`` project +in ``build.sbt`` From 28664ea8df7ea9f53f5d31e7cf313559821601a8 Mon Sep 17 00:00:00 2001 From: Albert Magyar Date: Thu, 26 Sep 2019 09:50:41 -0700 Subject: [PATCH 22/39] Update section header on Verilog support in chipyard tools --- docs/Customization/Incorporating-Verilog-Blocks.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/Customization/Incorporating-Verilog-Blocks.rst b/docs/Customization/Incorporating-Verilog-Blocks.rst index 2052eec6..8aecde15 100644 --- a/docs/Customization/Incorporating-Verilog-Blocks.rst +++ b/docs/Customization/Incorporating-Verilog-Blocks.rst @@ -158,8 +158,8 @@ write. :start-after: DOC include start: GCD test :end-before: DOC include end: GCD test -Support for Verilog in Downstream Berkeley Tools ------------------------------------------------- +Support for Verilog Within Chipyard Tool Flows +---------------------------------------------- There are important differences in how Verilog blackboxes are treated by downstream tools. Since they remain blackboxes in FIRRTL, their From f2939823ce30a1d8af780dc34b74f72e36ca718d Mon Sep 17 00:00:00 2001 From: Albert Magyar Date: Thu, 26 Sep 2019 10:09:02 -0700 Subject: [PATCH 23/39] Clean up paragraph on FIRRTL transform BlackBox support --- .../Incorporating-Verilog-Blocks.rst | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/docs/Customization/Incorporating-Verilog-Blocks.rst b/docs/Customization/Incorporating-Verilog-Blocks.rst index 8aecde15..64f064f8 100644 --- a/docs/Customization/Incorporating-Verilog-Blocks.rst +++ b/docs/Customization/Incorporating-Verilog-Blocks.rst @@ -17,7 +17,7 @@ algorithm. There are a few steps to adding a Verilog peripheral: * Instantiating the ``BlackBox`` and interfacing ``RegField`` entries * Setting up a chip ``Top`` and ``Config`` that use the peripheral -Adding a Verilog blackbox resource file +Adding a Verilog Blackbox Resource File --------------------------------------- As before, it is possible to incorporate peripherals as part of your @@ -112,7 +112,7 @@ previous memory-mapped PWM device example. Advanced Features of RegField Entries ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -One signficant difference from the PWM example is in the peripheral's +One significant difference from the PWM example is in the peripheral's memory map. ``RegField`` exposes polymorphic ``r`` and ``w`` methods that allow read- and write-only memory-mapped registers to be interfaced to hardware in multiple ways. @@ -162,18 +162,23 @@ Support for Verilog Within Chipyard Tool Flows ---------------------------------------------- There are important differences in how Verilog blackboxes are treated -by downstream tools. Since they remain blackboxes in FIRRTL, their -ability to be processed by FIRRTL transforms is limited, and some -advanced features of Chipyard may provide weaker support for -blackboxes. Note that the remainder of the target design may still -generally be transformed or augmented by any Chipyard FIRRTL -transform. +by various flows within the Chipyard framework. Some flows within +Chipyard rely on FIRRTL in order to provide robust, non-invasive +transformations of source code. Since Verilog blackboxes remain +blackboxes in FIRRTL, their ability to be processed by FIRRTL +transforms is limited, and some advanced features of Chipyard may +provide weaker support for blackboxes. Note that the remainder of the +design (the "non-Verilog" part of the design) may still generally be +transformed or augmented by any Chipyard FIRRTL transform. * Verilog blackboxes are fully supported for generating tapeout-ready RTL * HAMMER workflows offer robust support for integrating Verilog blackboxes * FireSim relies on FIRRTL transformations to generate a decoupled FPGA simulator. Therefore, support for Verilog blackboxes in FireSim is currently limited but rapidly evolving. Stay tuned! +* Custom FIRRTL transformations and analyses may sometimes be able to + handle blackbox Verilog, depending on the mechanism of the + particular transform As mentioned earlier in this section, ``BlackBox`` resource files must be integrated into the build process, so any project providing From 072a1e13cc12f6d61d2fd37dc75f256d8be3762e Mon Sep 17 00:00:00 2001 From: Harrison Liew Date: Thu, 26 Sep 2019 13:23:55 -0700 Subject: [PATCH 24/39] split Hammer doc into multiple files --- docs/VLSI/Advanced-Usage.rst | 29 ++++++ docs/VLSI/HAMMER.rst | 166 +---------------------------------- docs/VLSI/Tutorial.rst | 137 +++++++++++++++++++++++++++++ docs/VLSI/index.rst | 2 + 4 files changed, 170 insertions(+), 164 deletions(-) create mode 100644 docs/VLSI/Advanced-Usage.rst create mode 100644 docs/VLSI/Tutorial.rst diff --git a/docs/VLSI/Advanced-Usage.rst b/docs/VLSI/Advanced-Usage.rst new file mode 100644 index 00000000..163339d4 --- /dev/null +++ b/docs/VLSI/Advanced-Usage.rst @@ -0,0 +1,29 @@ +.. _advanced-usage: + +Advanced Usage +============== + +Alternative RTL Flows +--------------------- +The Make-based build system provided supports using Hammer without using RTL generated by Chipyard. To push a custom verilog module through, one only needs to export the following environment variables before ``make buildfile``. + +.. code-block:: shell + + export CUSTOM_VLOG= + export VLSI_TOP= + +Manual Step Execution & Dependency Tracking +------------------------------------------- +It is invariably necessary to debug certain steps of the flow, e.g. if the power strap settings need to be updated. The underlying Hammer commands support options such as ``--to_step``, ``--from_step``, and ``--only_step``. These allow you to control which steps of a particular action are executed. + +Make's dependency tracking can sometimes result in re-starting the entire flow when the user only wants to re-run a certain action. Hammer's build system has "redo" targets such as ``redo-syn`` and ``redo-par``. + +Say you need to update some power straps settings in ``example.yml`` and want to try out the new settings: + +.. code-block:: shell + + make redo-par HAMMER_REDO_ARGS='-p example.yml --only_step power_straps' + +Simulation +---------- +With the Synopsys plugin, RTL and gate-level simulation is supported using VCS. While this example does not implement any simulation, refer to Hammer's documentation for how to set it up for your design. diff --git a/docs/VLSI/HAMMER.rst b/docs/VLSI/HAMMER.rst index 28de651f..805a4d48 100644 --- a/docs/VLSI/HAMMER.rst +++ b/docs/VLSI/HAMMER.rst @@ -1,3 +1,5 @@ +.. _hammer: + Core HAMMER ================================ @@ -67,167 +69,3 @@ Several configuration variables are needed to configure your technology of choic First, choose the technology, e.g. ``vlsi.core.technology: asap7``, then point to the location with the PDK tarball with ``technology..tarball_dir`` or pre-installed directory with ``technology..install_dir`` and (if applicable) the plugin repository with ``vlsi.core.technology_path``. Technology-specific options such as supplies, MMMC corners, etc. are defined in their respective ``vlsi.inputs...`` configurations. Options for the most common use case are already defined in the technology's ``defaults.yml`` and can be overridden by the user. - -ASAP7 Tutorial -============== -The ``vlsi`` folder of this repository contains an example HAMMER flow with the SHA-3 accelerator and a dummy hard macro in the ASAP7 PDK. It is intended for use with the Cadence and Mentor tool plugins. - -Project Structure ------------------ - -This example gives a suggested file structure and build system. The ``vlsi/`` folder will eventually contain the following files and folders: - -* Makefile - - * Integration of Hammer's build system into Chipyard and abstracts away some Hammer commands. - -* build - - * Hammer output directory. Can be changed with the ``OBJ_DIR`` variable. - * Will contain subdirectories such as ``syn-rundir`` and ``par-rundir`` and the ``inputs.yml`` denoting the top module and input Verilog files. - -* bwrc-env.yml - - * An example of tool environment configuration for BWRC affiliates. Replace as necessary for your environment. - -* example-vlsi - - * Entry point to Hammer. Contains example placeholders for hooks. - -* example.v - - * Verilog wrapper around the accelerator and dummy hard macro. - -* example.yml - - * Hammer IR for this tutorial. - -* extra_libraries - - * Contains collateral for the dummy hard macro. - -* generated-src - - * All of the elaborated Chisel and FIRRTL. - -* hammer, hammer--plugins, hammer--plugin - - * Core, tool, tech repositories. - -Prerequisites -------------- - -* Python 3.4+ -* numpy and gdspy packages -* Genus, Innovus, and Calibre licenses -* For ASAP7 specifically: - - * Download the `ASAP7 PDK `__ tarball and do not extract it - * If you have additional ASAP7 hard macros, their LEF & GDS need to be 4x upscaled @ 4000 DBU precision - -Initial Setup -------------- -In the Chipyard root, run: - -.. code-block:: shell - - ``./scripts/init-vlsi.sh asap7`` - -to pull the HAMMER & plugin submodules. Note that for technologies other than ``asap7``, the tech submodule must be added in the ``vlsi`` folder first. - -Pull the Hammer environment into the shell: - -.. code-block:: shell - - cd vlsi - export HAMMER_HOME=$PWD/hammer - source $HAMMER_HOME/sourceme.sh - -Building the Design -------------------- -To elaborate the Sha3RocketConfig (Rocketchip w/ the accelerator) and set up all prerequisites for the build system to push just the accelerator + hard macro through the flow: - -.. code-block:: shell - - export MACROCOMPILER_MODE='--mode synflops' - export CONFIG=Sha3RocketConfig - export VLSI_TOP=Sha3AccelwBB - make buildfile - -Note that because the ASAP7 process does not yet have a memory compiler, flip-flop arrays are used instead. - -For the curious, Hammer generates a set of Make targets in ``build/hammer.d``. ``make buildfile`` needs to be re-run if Make variables are changed. - -Running the VLSI Flow ---------------------- - -example-vlsi -^^^^^^^^^^^^ -This is the entry script with placeholders for hooks. In the ``ExampleDriver`` class, a list of hooks is passed in the ``get_extra_par_hooks``. Hooks are additional snippets of python and TCL (via ``x.append()``) to extend the Hammer APIs. Hooks can be inserted using the ``make_pre/post/replacement_hook`` methods. - -example.yml -^^^^^^^^^^^ -This contains the Hammer configuration for this example project. Example clock constraints, power straps definitions, placement constraints, and pin constraints are given. Additional configuration for the extra libraries and tools are at the bottom. - -First, set ``technology.asap7.tarball_dir`` to where you downloaded the ASAP7 PDK. - -Synthesis -^^^^^^^^^ -.. code-block:: shell - - ``make syn`` - -Post-synthesis logs and collateral are in ``build/syn-rundir``. The Raw QoR data is available at ``build/syn-rundir/reports``, and methods to extract this information for design space exploration are a WIP. - -Place-and-Route -^^^^^^^^^^^^^^^ -.. code-block:: shell - - ``make par`` - -After completion, the final database can be opened in an interactive Innovus session via ``./build/par-rundir/generated-scripts/open_chip``. - -Intermediate database are written in ``build/par-rundir`` between each step of the ``par`` action, and can be restored in an interactive Innovus session as desired for debugging purposes. - -Timing reports are found in ``build/par-rundir/timingReports``. They are gzipped text files. - -DRC & LVS -^^^^^^^^^ -To run DRC & LVS, and view the results in Calibre: - -.. code-block:: shell - - make drc - ./build/drc-rundir/generated-scripts/view-drc - make lvs - ./build/lvs-rundir/generated-scripts/view-lvs - -Some DRC errors are expected from this PDK, as explained in the `ASAP7 plugin readme `__. - -Advanced Usage -============== - -Alternative RTL Flows ---------------------- -The Make-based build system provided supports using Hammer without using RTL generated by Chipyard. To push a custom verilog module through, one only needs to export the following environment variables before ``make buildfile``. - -.. code-block:: shell - - export CUSTOM_VLOG= - export VLSI_TOP= - -Manual Step Execution & Dependency Tracking -------------------------------------------- -It is invariably necessary to debug certain steps of the flow, e.g. if the power strap settings need to be updated. The underlying Hammer commands support options such as ``--to_step``, ``--from_step``, and ``--only_step``. These allow you to control which steps of a particular action are executed. - -Make's dependency tracking can sometimes result in re-starting the entire flow when the user only wants to re-run a certain action. Hammer's build system has "redo" targets such as ``redo-syn`` and ``redo-par``. - -Say you need to update some power straps settings in ``example.yml`` and want to try out the new settings: - -.. code-block:: shell - - make redo-par HAMMER_REDO_ARGS='-p example.yml --only_step power_straps' - -Simulation ----------- -With the Synopsys plugin, RTL and gate-level simulation is supported using VCS. While this example does not implement any simulation, refer to Hammer's documentation for how to set it up for your design. diff --git a/docs/VLSI/Tutorial.rst b/docs/VLSI/Tutorial.rst new file mode 100644 index 00000000..9f4262d2 --- /dev/null +++ b/docs/VLSI/Tutorial.rst @@ -0,0 +1,137 @@ +.. _tutorial: + +ASAP7 Tutorial +============== +The ``vlsi`` folder of this repository contains an example HAMMER flow with the SHA-3 accelerator and a dummy hard macro in the ASAP7 PDK. It is intended for use with the Cadence and Mentor tool plugins. + +Project Structure +----------------- + +This example gives a suggested file structure and build system. The ``vlsi/`` folder will eventually contain the following files and folders: + +* Makefile + + * Integration of Hammer's build system into Chipyard and abstracts away some Hammer commands. + +* build + + * Hammer output directory. Can be changed with the ``OBJ_DIR`` variable. + * Will contain subdirectories such as ``syn-rundir`` and ``par-rundir`` and the ``inputs.yml`` denoting the top module and input Verilog files. + +* bwrc-env.yml + + * An example of tool environment configuration for BWRC affiliates. Replace as necessary for your environment. + +* example-vlsi + + * Entry point to Hammer. Contains example placeholders for hooks. + +* example.v + + * Verilog wrapper around the accelerator and dummy hard macro. + +* example.yml + + * Hammer IR for this tutorial. + +* extra_libraries + + * Contains collateral for the dummy hard macro. + +* generated-src + + * All of the elaborated Chisel and FIRRTL. + +* hammer, hammer--plugins, hammer--plugin + + * Core, tool, tech repositories. + +Prerequisites +------------- + +* Python 3.4+ +* numpy and gdspy packages +* Genus, Innovus, and Calibre licenses +* For ASAP7 specifically: + + * Download the `ASAP7 PDK `__ tarball and do not extract it + * If you have additional ASAP7 hard macros, their LEF & GDS need to be 4x upscaled @ 4000 DBU precision + +Initial Setup +------------- +In the Chipyard root, run: + +.. code-block:: shell + + ``./scripts/init-vlsi.sh asap7`` + +to pull the HAMMER & plugin submodules. Note that for technologies other than ``asap7``, the tech submodule must be added in the ``vlsi`` folder first. + +Pull the Hammer environment into the shell: + +.. code-block:: shell + + cd vlsi + export HAMMER_HOME=$PWD/hammer + source $HAMMER_HOME/sourceme.sh + +Building the Design +------------------- +To elaborate the Sha3RocketConfig (Rocketchip w/ the accelerator) and set up all prerequisites for the build system to push just the accelerator + hard macro through the flow: + +.. code-block:: shell + + export MACROCOMPILER_MODE='--mode synflops' + export CONFIG=Sha3RocketConfig + export VLSI_TOP=Sha3AccelwBB + make buildfile + +Note that because the ASAP7 process does not yet have a memory compiler, flip-flop arrays are used instead. + +For the curious, Hammer generates a set of Make targets in ``build/hammer.d``. ``make buildfile`` needs to be re-run if Make variables are changed. + +Running the VLSI Flow +--------------------- + +example-vlsi +^^^^^^^^^^^^ +This is the entry script with placeholders for hooks. In the ``ExampleDriver`` class, a list of hooks is passed in the ``get_extra_par_hooks``. Hooks are additional snippets of python and TCL (via ``x.append()``) to extend the Hammer APIs. Hooks can be inserted using the ``make_pre/post/replacement_hook`` methods. + +example.yml +^^^^^^^^^^^ +This contains the Hammer configuration for this example project. Example clock constraints, power straps definitions, placement constraints, and pin constraints are given. Additional configuration for the extra libraries and tools are at the bottom. + +First, set ``technology.asap7.tarball_dir`` to where you downloaded the ASAP7 PDK. + +Synthesis +^^^^^^^^^ +.. code-block:: shell + + ``make syn`` + +Post-synthesis logs and collateral are in ``build/syn-rundir``. The Raw QoR data is available at ``build/syn-rundir/reports``, and methods to extract this information for design space exploration are a WIP. + +Place-and-Route +^^^^^^^^^^^^^^^ +.. code-block:: shell + + ``make par`` + +After completion, the final database can be opened in an interactive Innovus session via ``./build/par-rundir/generated-scripts/open_chip``. + +Intermediate database are written in ``build/par-rundir`` between each step of the ``par`` action, and can be restored in an interactive Innovus session as desired for debugging purposes. + +Timing reports are found in ``build/par-rundir/timingReports``. They are gzipped text files. + +DRC & LVS +^^^^^^^^^ +To run DRC & LVS, and view the results in Calibre: + +.. code-block:: shell + + make drc + ./build/drc-rundir/generated-scripts/view-drc + make lvs + ./build/lvs-rundir/generated-scripts/view-lvs + +Some DRC errors are expected from this PDK, as explained in the `ASAP7 plugin readme `__. diff --git a/docs/VLSI/index.rst b/docs/VLSI/index.rst index 44303769..8bc98b60 100644 --- a/docs/VLSI/index.rst +++ b/docs/VLSI/index.rst @@ -10,3 +10,5 @@ In particular, we aim to support the HAMMER physical design generator flow. Building-A-Chip HAMMER + Tutorial + Advanced-Usage From e7e229a416053c13cffdb48501fdb76fadcdb102 Mon Sep 17 00:00:00 2001 From: Harrison Liew Date: Thu, 26 Sep 2019 15:40:22 -0700 Subject: [PATCH 25/39] [skip ci] address comments, remove bwrc env vars, bump hammer --- docs/VLSI/Advanced-Usage.rst | 27 +++++++++++++++++++++++- docs/VLSI/HAMMER.rst | 2 +- docs/VLSI/Tutorial.rst | 14 +++++++----- vlsi/Makefile | 2 +- vlsi/bwrc-env.yml | 7 ------ vlsi/env.yml | 13 ++++++++++++ vlsi/extra_libraries/dco/ExampleDCO.gds | Bin 9472 -> 9536 bytes vlsi/hammer | 2 +- 8 files changed, 51 insertions(+), 16 deletions(-) delete mode 100644 vlsi/bwrc-env.yml create mode 100644 vlsi/env.yml diff --git a/docs/VLSI/Advanced-Usage.rst b/docs/VLSI/Advanced-Usage.rst index 163339d4..ba038f28 100644 --- a/docs/VLSI/Advanced-Usage.rst +++ b/docs/VLSI/Advanced-Usage.rst @@ -12,11 +12,36 @@ The Make-based build system provided supports using Hammer without using RTL gen export CUSTOM_VLOG= export VLSI_TOP= +``CUSTOM_VLOG`` breaks the dependency on the rest of the + +Under the Hood +-------------- +To uncover what is happening under the hood, here are the commands that are executed: + +For ``make syn``: + +.. code-block:: shell + + ./example-vlsi -e /path/to/env.yml -p /path/to/example.yml -p /path/to/inputs.yml --obj_dir /path/to/build syn + +``example-vlsi`` is the entry script as explained before, ``-e`` provides the environment yml, ``-p`` points to configuration yml/jsons, ``--obj_dir`` speficies the destination directory, and ``syn`` is the action. + +For ``make par``: + +.. code-block:: shell + + ./example-vlsi -e /path/to/env.yml -p /path/to/syn-output-full.json -o /path/to/par-input.json --obj_dir /path/to/build syn-to-par + ./example-vlsi -e /path/to/env.yml -p /path/to/par-input.json --obj_dir /path/to/build par + +A ``syn-to-par`` action translates the synthesis output configuration into an input configuration given by ``-o``. Then, this is passed to the ``par`` action. + +For more information about all the options that can be passed to the Hammer command-line driver, please see the Hammer documentation. + Manual Step Execution & Dependency Tracking ------------------------------------------- It is invariably necessary to debug certain steps of the flow, e.g. if the power strap settings need to be updated. The underlying Hammer commands support options such as ``--to_step``, ``--from_step``, and ``--only_step``. These allow you to control which steps of a particular action are executed. -Make's dependency tracking can sometimes result in re-starting the entire flow when the user only wants to re-run a certain action. Hammer's build system has "redo" targets such as ``redo-syn`` and ``redo-par``. +Make's dependency tracking can sometimes result in re-starting the entire flow when the user only wants to re-run a certain action. Hammer's build system has "redo" targets such as ``redo-syn`` and ``redo-par`` to run certain actions without typing out the entire Hammer command. Say you need to update some power straps settings in ``example.yml`` and want to try out the new settings: diff --git a/docs/VLSI/HAMMER.rst b/docs/VLSI/HAMMER.rst index 805a4d48..3a7def4b 100644 --- a/docs/VLSI/HAMMER.rst +++ b/docs/VLSI/HAMMER.rst @@ -62,7 +62,7 @@ Technology Plugins Hammer supports separately managed technology plugins to satisfy NDAs. You may be able to acquire access to certain pre-built technology plugins with permission from the technology vendor. Or, to build your own tech plugin, you need at least a ``.tech.json`` and ``defaults.yml``. An ``__init__.py`` is optional if there are any technology-specific methods or hooks to run. -The `ASAP7 plugin `__ is a good starting point for setting up a technology plugin. Refer to Hammer's documentation for the schema and setup instructions. +The `ASAP7 plugin `__ is a good starting point for setting up a technology plugin because it is an open-source example that is not suitable for taping out a chip. Refer to Hammer's documentation for the schema and detailed setup instructions. Several configuration variables are needed to configure your technology of choice. diff --git a/docs/VLSI/Tutorial.rst b/docs/VLSI/Tutorial.rst index 9f4262d2..c16d85d6 100644 --- a/docs/VLSI/Tutorial.rst +++ b/docs/VLSI/Tutorial.rst @@ -18,9 +18,9 @@ This example gives a suggested file structure and build system. The ``vlsi/`` fo * Hammer output directory. Can be changed with the ``OBJ_DIR`` variable. * Will contain subdirectories such as ``syn-rundir`` and ``par-rundir`` and the ``inputs.yml`` denoting the top module and input Verilog files. -* bwrc-env.yml +* env.yml - * An example of tool environment configuration for BWRC affiliates. Replace as necessary for your environment. + * A template file for tool environment configuration. Fill in the install and license server paths for your environment. * example-vlsi @@ -86,9 +86,13 @@ To elaborate the Sha3RocketConfig (Rocketchip w/ the accelerator) and set up all export VLSI_TOP=Sha3AccelwBB make buildfile -Note that because the ASAP7 process does not yet have a memory compiler, flip-flop arrays are used instead. +The ``MACROCOMPILER_MODE='--mode synflops'`` is needed because the ASAP7 process does not yet have a memory compiler. Therefore, flip-flop arrays are used instead. -For the curious, Hammer generates a set of Make targets in ``build/hammer.d``. ``make buildfile`` needs to be re-run if Make variables are changed. +The ``CONFIG=Sha3RocketConfig`` selects the target generator config in the same manner as the rest of the Chipyard framework. + +The ``VLSI_TOP=Sha3AccelwBB`` indicates that we are only interested in physical design of the accelerator block. If this variable is not set, the entire SoC will be pushed through physical design. + +For the curious, ``make buildfile`` generates a set of Make targets in ``build/hammer.d``. It needs to be re-run if environment variables are changed. Running the VLSI Flow --------------------- @@ -101,7 +105,7 @@ example.yml ^^^^^^^^^^^ This contains the Hammer configuration for this example project. Example clock constraints, power straps definitions, placement constraints, and pin constraints are given. Additional configuration for the extra libraries and tools are at the bottom. -First, set ``technology.asap7.tarball_dir`` to where you downloaded the ASAP7 PDK. +First, set ``technology.asap7.tarball_dir`` to the absolute path of where the downloaded the ASAP7 PDK tarball lives. Synthesis ^^^^^^^^^ diff --git a/vlsi/Makefile b/vlsi/Makefile index 3f493c6e..cc61b957 100644 --- a/vlsi/Makefile +++ b/vlsi/Makefile @@ -25,7 +25,7 @@ SMEMS_CACHE ?= $(tech_dir)/sram-cache.json SMEMS_HAMMER ?= $(build_dir)/$(long_name).mems.hammer.json MACROCOMPILER_MODE ?= -l $(SMEMS_CACHE) -hir $(SMEMS_HAMMER) OBJ_DIR ?= $(vlsi_dir)/build -ENV_YML ?= $(vlsi_dir)/bwrc-env.yml +ENV_YML ?= $(vlsi_dir)/env.yml INPUT_CONFS ?= example.yml HAMMER_EXEC ?= ./example-vlsi VLSI_TOP ?= $(TOP) diff --git a/vlsi/bwrc-env.yml b/vlsi/bwrc-env.yml deleted file mode 100644 index f68eab24..00000000 --- a/vlsi/bwrc-env.yml +++ /dev/null @@ -1,7 +0,0 @@ -mentor.mentor_home: "/tools/mentor" -mentor.MGLS_LICENSE_FILE: "1717@bwrcflex-1.eecs.berkeley.edu:1717@bwrcflex-2.eecs.berkeley.edu" -cadence.cadence_home: "/tools/cadence" -cadence.CDS_LIC_FILE: "5280@bwrcflex-1.eecs.berkeley.edu:5280@bwrcflex-2.eecs.berkeley.edu" -synopsys.synopsys_home: "/tools/synopsys" -synopsys.SNPSLMD_LICENSE_FILE: "1701@bwrcflex-1.eecs.berkeley.edu:1701@bwrcflex-2.eecs.berkeley.edu" -synopsys.MGLS_LICENSE_FILE: "1717@bwrcflex-1.eecs.berkeley.edu:1717@bwrcflex-2.eecs.berkeley.edu" diff --git a/vlsi/env.yml b/vlsi/env.yml new file mode 100644 index 00000000..c4e63038 --- /dev/null +++ b/vlsi/env.yml @@ -0,0 +1,13 @@ +# Base path to where Mentor tools are installed +mentor.mentor_home: "" +# Mentor license server/file +mentor.MGLS_LICENSE_FILE: "" +# Base path to where Cadence tools are installed +cadence.cadence_home: "" +# Cadence license server/file +cadence.CDS_LIC_FILE: "" +# Base path to where Synopsys tools are installed +synopsys.synopsys_home: "" +# Synopsys license server/files +synopsys.SNPSLMD_LICENSE_FILE: "" +synopsys.MGLS_LICENSE_FILE: "" diff --git a/vlsi/extra_libraries/dco/ExampleDCO.gds b/vlsi/extra_libraries/dco/ExampleDCO.gds index e60564bc3734d73f354e96ff65b354214ddee5f4..9990b41cb9422c5e429e78f59005ab44cd04acc0 100644 GIT binary patch literal 9536 zcmc(kUx-vy9LLYxx%bYR( zBtA%*ipF9uA_Y<}{Xq#?WFJI&SbPXE0x1v?kqyL`r23wFe&4&7+w{Xd^U#Hz&z&W&G^Hb>CR|@J zrAaf*ck$fjB-+EdXm8*fY~cYs^x}B(piPmJ$Ti;#;9&SEcUT)6iFVaLjAN}&9R%C`#8_arfJCnP_i-@#e?UG+bQ6%sHNUvX`6-t;zeu88 z_1B3{ZV;bDuKDq8=ck-Tj%;*-cVKl;u2DQ`JHBGIn;--}QFC_af?^$&?pekwkRT=ln#PY#JsB3J!x z@yQ@i%*utCy{G@c-{FaZ#X|B(XRSmi%)(lK8alQH;PYg5uZe^`b)(pmx)gz z*ZksN&L_iAe4))%|El=pHRl&eFKyZ;Sg-0S+{i8V8`sB$(H!+D^^|y;p*2E`~ ztNtqS$%^L`ze*YrO&-VN&Id79_SI>V)e3J7v ziCp!!icb#VIkt#IuKL|L*j_)`ljtTQk*j_zK3Nu@M6UViynWr(N$2ewu8wV2eaz4H z`a_cQHi=yI4~S15l=G6vRiE=d$$6hduKG*m{3Pdn61nDc-X|Y!{-5r@#jEc8DX+QL zuh0J(|E&1rIq^y4>h$W^~fd~%`qBy!C!+;x7+ zd(JPAXjlD9;**!fCy}fE3GvA>@k!*Wzf*j2SbP$>>i3FI_K8m-SN(SJ$@$`w$TdIx z-SDQXW9~RVC34ljARaj`K8alQ4~tJ86Q4w``UB#VJH#iEXMMMRmhtbD9Q#Fvy`#q1 zoW$sTPEj;u4ch(Pz&I{&b2rtRWhQ7Q0 z|J(O@{X@z6e|rA1x4$&mW|7eTFTw3Q+Q;Pnm9eJA{~uass(@6*p!KOO`1nK{#cihC8Skl8tHb^5(GUBIa23{%&Q?r&XFO8>xPMQz)<3X$`AhG4Tn#FjPb&8H z41KV7M|EVzcf?+c`L1H-;f~aYs{JF?_dlv_+gl&myv+A{?lh{l+_PHYsYcbheXDJ1 zRP6=dYDXGXd(pSruGeha8tP9nbkEswba}%o@&j?vHx%m3&8#sF1JZJA#B)@|Ao?knpp7C7%(b^rT(;PbF*r M_3LG=TmnP$4-bSh761SM literal 9472 zcmc(kPi$0G6voe+whs!mOtqG_Rz(pp%AZn&wxXs$+nAs-qz17?`)|fd7?`GDBsL^X zhz2*NgcU+a7sQ5@k+?8MA}d2!H4?Xm#BPim7mXVidft2A*Li(DPwbtAZ^3W!4Zm~W z+_`hlovHYe$sCn7FSF(ssg-7FkS=*N{#ddZzi@W+LR2*Z~B|zlUv}Enw$O(_+&eL zQghSqhEMK=Pik)Zz3|C?_@w5he+WK#7(S`F=?}sukHIH3H~j*9asoc7x#>^BC#T?( znw$PKeDWN8QghS)1U`8IKB>9sUxZIyf=_C0`d8tT*WiGpZpp= zsk!Ojf=_-ApVZv+@4zST!Y4I1{d@4qpWu_4TfX;gd{T4M-v^&O0H4&{^!LCgyWo?WoBng~ z$?fn-%}xJd_~b_Tq~@l-4nA22pVZv)<*&#mJr6z@}`qBJLh2I|{U-Vk;yX?d4yJTwrjrr`mB>OI@d3^oG?>`*>`b@OmN%mb* zbJJ(vCE0h$)cza0fA(FHeV5eS9G`ucWZxw>;FEWw;f2)P^l!l@`Mr0g9TUV=|*Zu9sPr@gs;FFr0 zK7aQiC*YHsoBkliCy&7=H8=f3@X5pQNzF~a7e3h!pVZv+yWx|2;gg!1{tozLJA6`e z)87oA+ybA}-1M8_ldbSc&EtM_e#ZX!bWil3x85#u!<EeHR88=`nc|qnx2-+!S%V+wbkq&3?#kk z^luEJ=LeatlC>@Vk>1`_)(ZS-9k?$q>stKrVrl$@LxtKOgO?_CE&l0Zp)ff-=1?P; zmRED~V2eLh`f&Jkp*TD?v}^Y}j+Oje@Otvc&%9rlTHWjhGZNfOZC09eMoRg@@Kj;q zgW~9!($rA9>;0@>NU65VwOajbO0^ExY7M!RYR|h?YfPKB7hJ0~rOli3s%S}@w>_@+ z)|NJJovzg$&q_AF_I0VPYFFU8ePUr{9bIHjb)K4CSx1+bQ=P53m34GsIn{YKF+aMb zoa$^#%#SW6r#d?m^P|hisZK{?eslpj)!ChxpDxEbor(GBcC2%1A=t~uOGWPG&O1sm zo2cZx(;W}{OYEMUci{JC6ZhoY8OFo;F5i>ue2<3jf4Pq9`~Pk(_`H_uxUR>c*_Cx% zKOaXE^W*w?J(8Fo*ZpH4F+Z;RSuQa@uKVljiTQEe?++&C$F=|Tg`bSr8P2))?_Wrq r2Ay}1o@}C$^A7TIE>X#O2YE3$Pfk0?P)~S%56=Dr12`+MQC7>}JmjyZ diff --git a/vlsi/hammer b/vlsi/hammer index b837b3fa..946c4f41 160000 --- a/vlsi/hammer +++ b/vlsi/hammer @@ -1 +1 @@ -Subproject commit b837b3fa321cce78998811d3bc842463e58e5745 +Subproject commit 946c4f416709663651580f7c4c1be2e2652dff6f From 8fffc1c67069081e1a9da29727cee098df552c70 Mon Sep 17 00:00:00 2001 From: Harrison Liew Date: Thu, 26 Sep 2019 22:47:17 -0700 Subject: [PATCH 26/39] [skip ci] make dco libs in example folder for consistency --- vlsi/example.yml | 12 ++++++------ .../extra_libraries/{dco => example}/ExampleDCO.gds | Bin .../extra_libraries/{dco => example}/ExampleDCO.lef | 0 .../{dco => example}/ExampleDCO_PVT_0P63V_100C.lib | 0 .../{dco => example}/ExampleDCO_PVT_0P77V_0C.lib | 0 5 files changed, 6 insertions(+), 6 deletions(-) rename vlsi/extra_libraries/{dco => example}/ExampleDCO.gds (100%) rename vlsi/extra_libraries/{dco => example}/ExampleDCO.lef (100%) rename vlsi/extra_libraries/{dco => example}/ExampleDCO_PVT_0P63V_100C.lib (100%) rename vlsi/extra_libraries/{dco => example}/ExampleDCO_PVT_0P77V_0C.lib (100%) diff --git a/vlsi/example.yml b/vlsi/example.yml index e641f8c2..d8ca594b 100644 --- a/vlsi/example.yml +++ b/vlsi/example.yml @@ -76,11 +76,11 @@ vlsi.technology.extra_libraries_meta: ["append", "deepsubst"] vlsi.technology.extra_libraries: - library: nldm liberty file_deepsubst_meta: "local" - nldm liberty file: "extra_libraries/dco/ExampleDCO_PVT_0P63V_100C.lib" + nldm liberty file: "extra_libraries/example/ExampleDCO_PVT_0P63V_100C.lib" lef file_deepsubst_meta: "local" - lef file: "extra_libraries/dco/ExampleDCO.lef" + lef file: "extra_libraries/example/ExampleDCO.lef" gds file_deepsubst_meta: "local" - gds file: "extra_libraries/dco/ExampleDCO.gds" + gds file: "extra_libraries/example/ExampleDCO.gds" corner: nmos: "slow" pmos: "slow" @@ -90,11 +90,11 @@ vlsi.technology.extra_libraries: GND: "0 V" - library: nldm liberty file_deepsubst_meta: "local" - nldm liberty file: "extra_libraries/dco/ExampleDCO_PVT_0P77V_0C.lib" + nldm liberty file: "extra_libraries/example/ExampleDCO_PVT_0P77V_0C.lib" lef file_deepsubst_meta: "local" - lef file: "extra_libraries/dco/ExampleDCO.lef" + lef file: "extra_libraries/example/ExampleDCO.lef" gds file_deepsubst_meta: "local" - gds file: "extra_libraries/dco/ExampleDCO.gds" + gds file: "extra_libraries/example/ExampleDCO.gds" corner: nmos: "fast" pmos: "fast" diff --git a/vlsi/extra_libraries/dco/ExampleDCO.gds b/vlsi/extra_libraries/example/ExampleDCO.gds similarity index 100% rename from vlsi/extra_libraries/dco/ExampleDCO.gds rename to vlsi/extra_libraries/example/ExampleDCO.gds diff --git a/vlsi/extra_libraries/dco/ExampleDCO.lef b/vlsi/extra_libraries/example/ExampleDCO.lef similarity index 100% rename from vlsi/extra_libraries/dco/ExampleDCO.lef rename to vlsi/extra_libraries/example/ExampleDCO.lef diff --git a/vlsi/extra_libraries/dco/ExampleDCO_PVT_0P63V_100C.lib b/vlsi/extra_libraries/example/ExampleDCO_PVT_0P63V_100C.lib similarity index 100% rename from vlsi/extra_libraries/dco/ExampleDCO_PVT_0P63V_100C.lib rename to vlsi/extra_libraries/example/ExampleDCO_PVT_0P63V_100C.lib diff --git a/vlsi/extra_libraries/dco/ExampleDCO_PVT_0P77V_0C.lib b/vlsi/extra_libraries/example/ExampleDCO_PVT_0P77V_0C.lib similarity index 100% rename from vlsi/extra_libraries/dco/ExampleDCO_PVT_0P77V_0C.lib rename to vlsi/extra_libraries/example/ExampleDCO_PVT_0P77V_0C.lib From c6bdeda9ed3be61cd225de5520cfa19766f8d492 Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Thu, 26 Sep 2019 23:10:51 -0700 Subject: [PATCH 27/39] small fixes + cleaner example explanation [ci skip] --- docs/Customization/Firrtl-Transforms.rst | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/docs/Customization/Firrtl-Transforms.rst b/docs/Customization/Firrtl-Transforms.rst index 64aba247..4e689192 100644 --- a/docs/Customization/Firrtl-Transforms.rst +++ b/docs/Customization/Firrtl-Transforms.rst @@ -13,7 +13,7 @@ Where to add transforms In Chipyard, the FIRRTL compiler is called multiple times to create a "Top" file that contains the DUT and a "Harness" file containing the test harness, which instantiates the DUT. The "Harness" file does not contain the DUT's module definition or any of its submodules. -This done by the ``tapeout`` SBT project (located in ``tools/barstools/tapeout``) which calls ``GenerateTopAndHarness`` (a function that wraps the multiple FIRRTL compiler calls and extra transforms). +This is done by the ``tapeout`` SBT project (located in ``tools/barstools/tapeout``) which calls ``GenerateTopAndHarness`` (a function that wraps the multiple FIRRTL compiler calls and extra transforms). .. literalinclude:: ../../common.mk :language: make @@ -24,6 +24,8 @@ If you look inside of the `tools/barstools/tapeout/src/main/scala/transforms/Gen you can see that FIRRTL is invoked twice, once for the "Top" and once for the "Harness". If you want to add transforms to just modify the DUT, you can add them to ``topTransforms``. Otherwise, if you want to add transforms to just modify the test harness, you can add them to ``harnessTransforms``. +For more information on Barstools, please visit the :ref:`Barstools` section. + Examples of transforms ---------------------- @@ -38,7 +40,9 @@ adding them to your Chisel source or by creating a serialized annotation ``json` **The recommended way to annotate something is to do it in the Chisel source, but not all annotation types have Chisel APIs**. Here is an example of adding a ``DontTouchAnnotation`` within the Chisel source. This annotation -makes sure that a particular signal is not removed by the "Dead Code Elimination" pass in FIRRTL: +makes sure that a particular signal is not removed by the "Dead Code Elimination" pass in FIRRTL. +The example below shows both how to directly annotate the signal with the ``annotate`` function and the ``DontTouchAnnotation`` +class as well as the Chisel wrapper function called ``dontTouch`` that does this automatically for you (more `dontTouch `__ information): .. code-block:: scala @@ -55,8 +59,9 @@ makes sure that a particular signal is not removed by the "Dead Code Elimination def toFirrtl = DontTouchAnnotation(some_signal.toNamed) }) - // or use the wrapper for this - // chisel3.experimental.dontTouch(some_signal) + // or use the Chisel wrapper for this + + chisel3.dontTouch(some_signal) ... } From 802c11dbefd254fc02f592c6e52175c2e3057e94 Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Thu, 26 Sep 2019 23:16:57 -0700 Subject: [PATCH 28/39] add some extra clarity [ci skip] --- docs/Customization/Firrtl-Transforms.rst | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/docs/Customization/Firrtl-Transforms.rst b/docs/Customization/Firrtl-Transforms.rst index 4e689192..f25bd43f 100644 --- a/docs/Customization/Firrtl-Transforms.rst +++ b/docs/Customization/Firrtl-Transforms.rst @@ -41,8 +41,10 @@ adding them to your Chisel source or by creating a serialized annotation ``json` Here is an example of adding a ``DontTouchAnnotation`` within the Chisel source. This annotation makes sure that a particular signal is not removed by the "Dead Code Elimination" pass in FIRRTL. -The example below shows both how to directly annotate the signal with the ``annotate`` function and the ``DontTouchAnnotation`` -class as well as the Chisel wrapper function called ``dontTouch`` that does this automatically for you (more `dontTouch `__ information): +The example below shows two ways to annotate the signal: + +* directly annotate the signal with the ``annotate`` function and the ``DontTouchAnnotation`` class if there is no Chisel API for it (note: most FIRRTL annotations have Chisel APIs for them) +* use the Chisel API/wrapper function called ``dontTouch`` that does this automatically for you (more `dontTouch `__ information): .. code-block:: scala @@ -55,13 +57,15 @@ class as well as the Chisel wrapper function called ``dontTouch`` that does this class Submodule extends Module { ... val some_signal := ... + + // how to annotate WITHOUT a Chisel API/wrapper annotate(new ChiselAnnotation { def toFirrtl = DontTouchAnnotation(some_signal.toNamed) }) - // or use the Chisel wrapper for this - + // how to annotate if there is a Chisel API/wrapper chisel3.dontTouch(some_signal) + ... } From 932357ef5673b96b43eda2a8bf9c82e85c16cf8c Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Fri, 27 Sep 2019 00:29:24 -0700 Subject: [PATCH 29/39] cleaner + more correct documents [ci skip] --- docs/Advanced-Usage/Chip-Communication.rst | 124 ++++++++++++++---- .../src/main/scala/RocketConfigs.scala | 11 +- 2 files changed, 105 insertions(+), 30 deletions(-) diff --git a/docs/Advanced-Usage/Chip-Communication.rst b/docs/Advanced-Usage/Chip-Communication.rst index 8f31d931..31a55007 100644 --- a/docs/Advanced-Usage/Chip-Communication.rst +++ b/docs/Advanced-Usage/Chip-Communication.rst @@ -3,40 +3,104 @@ Communicating with the Chip/DUT =============================== -What good is a chip if it can't communicate with the outside world? Chipyard designs communicate to the outside world in -one of two ways: +What good is a chip/DUT if it can't communicate with the outside world? Chipyard designs +communicate to the outside world in one of two ways: -* using the Front-End Server (FESVR) -* using Rocket Chip's JTAG/DTM interface. +* using the Tethered Serial Interface (TSI) or the Debug Module Interface (DMI) with the Front-End Server (FESVR) to communicate with the design +* using the JTAG interface with OpenOCD and GDB to communicate with the design -Debugging with the Front-End Server (FESVR) -------------------------------------------- +Using the Tethered Serial Interface (TSI) or the Debug Module Interface (DMI) +----------------------------------------------------------------------------- -By default, Chipyard simulations are setup to use the Front-End Server (FESVR) and extra infrastructure to bringup the DUT. However, FESVR can also be used to -bringup a DUT/Chip when a tapeout is completed. FESVR is a C++ library that gives a simple API to reset, send messages, and run programs on a DUT. -It can be added used simulators (VCS, Verilator, FireSim) as well as in a bringup sequence for a taped out chip. +If you are using TSI or the DMI to communicate with the target (DUT/chip), you are using +the Front-End Server (FESVR) to facilitate communication between the host machine and the target. -In the case of a simulator like VCS/Verilator, FESVR functions are converted into Tethered Serial Interface (TSI) commands. -These TSI commands are simple R/W commands that are able to probe the DUT's memory space. In simulation, these TSI commands connect to -a ``SimSerial`` (located in the ``generators/testchipip`` project) simulation C++ class that is added to simulation. This ``SimSerial`` -device sends the TSI command to the DUT which contains a ``SerialAdapter`` (located in the ``generators/testchipip`` project) that converts -the TSI commands to TileLink requests. In simulation, FESVR resets the DUT, and writes into memory the test program. This is currently the fastest +Primer on the Front-End Server (FESVR) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +FESVR is a C++ library that manages communication +between a host machine and a RISC-V target. For debugging, it provides a simple API to reset, +send messages, and run programs on a DUT but it also provides peripheral device emulation. +It can be added used simulators (VCS, Verilator, FireSim) as well as in a bringup sequence +for a taped out chip. + +Specifically, FESVR uses the Host Target Interface (HTIF), a communication bus for the hardware, +to speak with the target. HTIF is a non-standard Berkeley extension that uses a FIFO non-blocking +interface to communicate with the target. + +Using the Tethered Serial Interface (TSI) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +By default, Chipyard uses the Tethered Serial Interface (TSI) to communicate with the target. +TSI is the implementation of the HTIF interface that is used to send commands to the +RISC-V target. These TSI commands are simple R/W commands +that are able to probe the DUT's memory space. In simulation, these TSI commands connect +to a ``SimSerial`` (located in the ``generators/testchipip`` project) simulation C++ +class that is added to simulation. This ``SimSerial`` device sends the TSI command to +the DUT which contains a ``SerialAdapter`` (located in the ``generators/testchipip`` +project) that converts the TSI commands to TileLink requests. In simulation, FESVR +resets the DUT, and writes into memory the test program. This is currently the fastest mechanism to simulate the DUT. -In the case of a chip tapeout bringup, FESVR is used as a library ... +In the case of a chip tapeout bringup, TSI commands can be sent over a modified communication +medium to communicate with the chip. For example, some Berkeley tapeouts have a FPGA +with a RISC-V soft-core that runs FESVR. The FESVR on the soft-core sends TSI commands +to a TSI to TileLink converter living on the FPGA (i.e. ``SerialAdapter``). Then this converter +sends the converted TileLink commands over a serial link to the chip. -to a main C++ that is run to communicate to a physical chip. In this case, FESVR is normally modified to specify the communication -medium (i.e. send message with TSI over pins in a particular protocol). +Using the Debug Module Interface (DMI) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Debugging with DTM/JTAG ------------------------ - -Chipyard is not setup to use the Debug Test Module (DTM) to bringup the core. +Another option to bringup the target is to use the Debug Module Interface (DMI) provided by Rocket Chip. +In this case, a Debug Test Module (DTM) must exist in the target that communicates with the DMI. +The DTM is given in the RISC-V Debug Specification and is responsible for managing communication between +the target and whatever lives on the other side of the DMI (in this case FESVR). This is added by default +to the Rocket Chip ``Subsystem`` by having the ``HasPeripheryDebug`` and ``HasPeripheryDebugModuleImp`` mixins. +Chipyard disables the DTM by default so that it can use the TSI interface. This is because the DTM executes a small loop of code to write the test binary byte-wise into memory -while the default ``SimSerial``/``SerialAdapter``/``FESVR`` interface directly writes to memory. -However, if you want to use JTAG, you must do the following steps to setup a DTM enabled system. +while the default ``SimSerial``/``SerialAdapter``/TSI interface directly writes to memory. -Creating a DTM/JTAG Config +Starting the TSI or DMI Simulation +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Since Chipyard uses TSI by default, you can run a TSI based simulation by running any of the default +configurations. For example: + +.. code-block:: bash + + cd sims/verilator + # or + cd sims/vcs + + make CONFIG=LargeBoomConfig run-asm-tests + +If you would like to build a DMI system with a Chipyard configuration, the you must create a +top-level system with the DTM as well as a config to use that top-level system. + +.. literalinclude:: ../../generators/example/src/main/scala/RocketConfigs.scala + :language: scala + :start-after: DOC include start: DmiRocket + :end-before: DOC include end: DmiRocket + +In this example, the ``WithDTMTop`` mixin specifies that the top-level SoC will instantiate a DTM. +The rest of the mixins specify the rest of the system (cores, accelerators, etc). + +.. code-block:: bash + + cd sims/verilator + # or + cd sims/vcs + + make CONFIG=dmiRocketConfig TOP=TopWithDTM MODEL=TestHarnessWithDTM + +Using the JTAG Interface +------------------------ + +The main way to use JTAG with a Rocket Chip based system is to instantiate the Debug Test Module (DTM) +and configure it to use a JTAG interface (by default the DTM is setup to use the DMI interface mentioned above). +However, if you want to use JTAG, you must do the following steps to setup a DTM+JTAG enabled system. + +Creating a DTM+JTAG Config ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ First, a DTM config must be created for the system that you want to create. @@ -48,10 +112,11 @@ This involves specifying the SoC top-level to add a DTM as well as configuring t :end-before: DOC include end: JtagRocket In this example, the ``WithDTMTop`` mixin specifies that the top-level SoC will instantiate a DTM. -The ``WithJtagDTM`` will configure that instantiated DTM to use JTAG as the bringup method (note: this can be removed if you want a DTM-only bringup). +The ``WithJtagDTM`` will configure that instantiated DTM to use JTAG as the bringup method (note: +this can be removed if you want a DMI-only bringup). The rest of the mixins specify the rest of the system (cores, accelerators, etc). -Starting the DTM Simulation +Starting the DTM+JTAG Simulation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ After creating the config, call the ``make`` command like the following: @@ -62,10 +127,11 @@ After creating the config, call the ``make`` command like the following: # or cd sims/vcs - make CONFIG=DTMBoomConfig TOP=TopWithDTM MODEL=TestHarnessWithDTM + make CONFIG=jtagRocketConfig TOP=TopWithDTM MODEL=TestHarnessWithDTM -In this example, this will use the config that you previously specified, as well as set the other parameters that are needed to satisfy the build system. -After that point, you should have a JTAG enabled simulation that you can attach to using OpenOCD and GDB! +In this example, this will use the config that you previously specified, as well as set +the other parameters that are needed to satisfy the build system. After that point, you +should have a JTAG enabled simulation that you can attach to using OpenOCD and GDB! Debugging with JTAG ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/generators/example/src/main/scala/RocketConfigs.scala b/generators/example/src/main/scala/RocketConfigs.scala index 2275549f..d5a090b4 100644 --- a/generators/example/src/main/scala/RocketConfigs.scala +++ b/generators/example/src/main/scala/RocketConfigs.scala @@ -34,13 +34,22 @@ class RoccRocketConfig extends Config( // DOC include start: JtagRocket class jtagRocketConfig extends Config( new WithDTMTop ++ // use top with dtm - new freechips.rocketchip.subsystem.WithJtagDTM ++ // add jtag/DTM module to coreplex + new freechips.rocketchip.subsystem.WithJtagDTM ++ // add jtag+DTM module to coreplex new WithBootROM ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.system.BaseConfig) // DOC include end: JtagRocket +// DOC include start: DmiRocket +class dmiRocketConfig extends Config( + new WithDTMTop ++ // use top with dtm + new WithBootROM ++ + new freechips.rocketchip.subsystem.WithInclusiveCache ++ + new freechips.rocketchip.subsystem.WithNBigCores(1) ++ + new freechips.rocketchip.system.BaseConfig) +// DOC include end: DmiRocket + // DOC include start: PWMRocketConfig class PWMRocketConfig extends Config( new WithPWMTop ++ // use top with tilelink-controlled PWM From f24eba30f674ffba6f42142a59bad1e58d7f8e79 Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Fri, 27 Sep 2019 00:32:47 -0700 Subject: [PATCH 30/39] change order of dontTouch | make more concise [ci skip] --- docs/Customization/Firrtl-Transforms.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/Customization/Firrtl-Transforms.rst b/docs/Customization/Firrtl-Transforms.rst index f25bd43f..808082e0 100644 --- a/docs/Customization/Firrtl-Transforms.rst +++ b/docs/Customization/Firrtl-Transforms.rst @@ -39,12 +39,11 @@ adding them to your Chisel source or by creating a serialized annotation ``json` (note: annotating the Chisel source will automatically serialize the annotation as a ``json`` snippet into the build system for you). **The recommended way to annotate something is to do it in the Chisel source, but not all annotation types have Chisel APIs**. -Here is an example of adding a ``DontTouchAnnotation`` within the Chisel source. This annotation -makes sure that a particular signal is not removed by the "Dead Code Elimination" pass in FIRRTL. -The example below shows two ways to annotate the signal: +The example below shows two ways to annotate the signal using the ``DontTouchAnnotation`` +(makes sure that a particular signal is not removed by the "Dead Code Elimination" pass in FIRRTL): -* directly annotate the signal with the ``annotate`` function and the ``DontTouchAnnotation`` class if there is no Chisel API for it (note: most FIRRTL annotations have Chisel APIs for them) * use the Chisel API/wrapper function called ``dontTouch`` that does this automatically for you (more `dontTouch `__ information): +* directly annotate the signal with the ``annotate`` function and the ``DontTouchAnnotation`` class if there is no Chisel API for it (note: most FIRRTL annotations have Chisel APIs for them) .. code-block:: scala @@ -58,14 +57,15 @@ The example below shows two ways to annotate the signal: ... val some_signal := ... + // MAIN WAY TO USE `dontTouch` + // how to annotate if there is a Chisel API/wrapper + chisel3.dontTouch(some_signal) + // how to annotate WITHOUT a Chisel API/wrapper annotate(new ChiselAnnotation { def toFirrtl = DontTouchAnnotation(some_signal.toNamed) }) - // how to annotate if there is a Chisel API/wrapper - chisel3.dontTouch(some_signal) - ... } From 35566195dbbca8cc7b724769aae949757f3c87aa Mon Sep 17 00:00:00 2001 From: Harrison Liew Date: Fri, 27 Sep 2019 09:37:27 -0700 Subject: [PATCH 31/39] [skip ci] address comments, instantiate Sha3Accel module --- docs/VLSI/Advanced-Usage.rst | 8 +-- docs/VLSI/Tutorial.rst | 13 ++-- vlsi/example.v | 127 ++++++----------------------------- 3 files changed, 28 insertions(+), 120 deletions(-) diff --git a/docs/VLSI/Advanced-Usage.rst b/docs/VLSI/Advanced-Usage.rst index ba038f28..9d0afd76 100644 --- a/docs/VLSI/Advanced-Usage.rst +++ b/docs/VLSI/Advanced-Usage.rst @@ -5,14 +5,14 @@ Advanced Usage Alternative RTL Flows --------------------- -The Make-based build system provided supports using Hammer without using RTL generated by Chipyard. To push a custom verilog module through, one only needs to export the following environment variables before ``make buildfile``. +The Make-based build system provided supports using Hammer without using RTL generated by Chipyard. To push a custom verilog module through, one only needs to give the following environment variables ``make buildfile`` (or edit them directly in the Makefile). .. code-block:: shell - export CUSTOM_VLOG= - export VLSI_TOP= + CUSTOM_VLOG= + VLSI_TOP= -``CUSTOM_VLOG`` breaks the dependency on the rest of the +``CUSTOM_VLOG`` breaks the dependency on the rest of the Chipyard infrastructure and does not start any Chisel/FIRRTL elaboration. ``VLSI_TOP`` selects the top module from your custom Verilog files. Under the Hood -------------- diff --git a/docs/VLSI/Tutorial.rst b/docs/VLSI/Tutorial.rst index c16d85d6..bab71d4a 100644 --- a/docs/VLSI/Tutorial.rst +++ b/docs/VLSI/Tutorial.rst @@ -2,7 +2,7 @@ ASAP7 Tutorial ============== -The ``vlsi`` folder of this repository contains an example HAMMER flow with the SHA-3 accelerator and a dummy hard macro in the ASAP7 PDK. It is intended for use with the Cadence and Mentor tool plugins. +The ``vlsi`` folder of this repository contains an example HAMMER flow with the SHA-3 accelerator and a dummy hard macro. This example tutorial uses the built-in ASAP7 technology plugin and requires access to the included Cadence and Mentor tool plugin submodules. Cadence is necessary for synthesis & place-and-route, while Mentor is needed for DRC & LVS. Project Structure ----------------- @@ -81,18 +81,15 @@ To elaborate the Sha3RocketConfig (Rocketchip w/ the accelerator) and set up all .. code-block:: shell - export MACROCOMPILER_MODE='--mode synflops' - export CONFIG=Sha3RocketConfig - export VLSI_TOP=Sha3AccelwBB - make buildfile + make buildfile MACROCOMPILER_MODE='--mode synflops' CONFIG=Sha3RocketConfig VLSI_TOP=Sha3AccelwBB The ``MACROCOMPILER_MODE='--mode synflops'`` is needed because the ASAP7 process does not yet have a memory compiler. Therefore, flip-flop arrays are used instead. -The ``CONFIG=Sha3RocketConfig`` selects the target generator config in the same manner as the rest of the Chipyard framework. +The ``CONFIG=Sha3RocketConfig`` selects the target generator config in the same manner as the rest of the Chipyard framework. This elaborates a Rocket-chip with the Sha3Accel module. -The ``VLSI_TOP=Sha3AccelwBB`` indicates that we are only interested in physical design of the accelerator block. If this variable is not set, the entire SoC will be pushed through physical design. +The ``VLSI_TOP=Sha3AccelwBB`` indicates that we are only interested in physical design of the accelerator block. If this variable is not set, the entire SoC will be pushed through physical design. Note that you should not set the ``TOP`` variable because it is used during Chisel elaboration. -For the curious, ``make buildfile`` generates a set of Make targets in ``build/hammer.d``. It needs to be re-run if environment variables are changed. +For the curious, ``make buildfile`` generates a set of Make targets in ``build/hammer.d``. It needs to be re-run if environment variables are changed. It is recommended that you edit these variables directly in the Makefile rather than exporting them to your shell environment. Running the VLSI Flow --------------------- diff --git a/vlsi/example.v b/vlsi/example.v index bd0d3f9d..dbc7bec5 100644 --- a/vlsi/example.v +++ b/vlsi/example.v @@ -1,4 +1,4 @@ -// Extracted Sha3Accel w/ a blackbox (a dummy DCO) included inside +// Sha3Accel w/ a blackbox (a dummy DCO) included inside module Sha3AccelwBB( // @[:example.TestHarness.Sha3RocketConfig.fir@135905.2] input clock, // @[:example.TestHarness.Sha3RocketConfig.fir@135906.4] @@ -25,84 +25,24 @@ module Sha3AccelwBB( // @[:example.TestHarness.Sha3RocketConfig.fir@135905.2] input sleep_b, output dco_clock ); - wire clock; // from dummy DCO - wire ctrl_clock; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] - wire ctrl_reset; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] - wire ctrl_io_rocc_req_val; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] - wire ctrl_io_rocc_req_rdy; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] - wire [1:0] ctrl_io_rocc_funct; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] - wire [63:0] ctrl_io_rocc_rs1; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] - wire [63:0] ctrl_io_rocc_rs2; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] - wire ctrl_io_busy; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] - wire ctrl_io_dmem_req_val; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] - wire ctrl_io_dmem_req_rdy; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] - wire [6:0] ctrl_io_dmem_req_tag; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] - wire [31:0] ctrl_io_dmem_req_addr; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] - wire [4:0] ctrl_io_dmem_req_cmd; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] - wire ctrl_io_dmem_resp_val; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] - wire [6:0] ctrl_io_dmem_resp_tag; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] - wire [63:0] ctrl_io_dmem_resp_data; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] - wire [4:0] ctrl_io_round; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] - wire ctrl_io_absorb; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] - wire [4:0] ctrl_io_aindex; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] - wire ctrl_io_init; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] - wire ctrl_io_write; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] - wire [2:0] ctrl_io_windex; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] - wire [63:0] ctrl_io_buffer_out; // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] - wire dpath_clock; // @[sha3.scala 82:21:example.TestHarness.Sha3RocketConfig.fir@135936.4] - wire dpath_reset; // @[sha3.scala 82:21:example.TestHarness.Sha3RocketConfig.fir@135936.4] - wire dpath_io_absorb; // @[sha3.scala 82:21:example.TestHarness.Sha3RocketConfig.fir@135936.4] - wire dpath_io_init; // @[sha3.scala 82:21:example.TestHarness.Sha3RocketConfig.fir@135936.4] - wire dpath_io_write; // @[sha3.scala 82:21:example.TestHarness.Sha3RocketConfig.fir@135936.4] - wire [4:0] dpath_io_round; // @[sha3.scala 82:21:example.TestHarness.Sha3RocketConfig.fir@135936.4] - wire [4:0] dpath_io_aindex; // @[sha3.scala 82:21:example.TestHarness.Sha3RocketConfig.fir@135936.4] - wire [63:0] dpath_io_message_in; // @[sha3.scala 82:21:example.TestHarness.Sha3RocketConfig.fir@135936.4] - wire [63:0] dpath_io_hash_out_0; // @[sha3.scala 82:21:example.TestHarness.Sha3RocketConfig.fir@135936.4] - wire [63:0] dpath_io_hash_out_1; // @[sha3.scala 82:21:example.TestHarness.Sha3RocketConfig.fir@135936.4] - wire [63:0] dpath_io_hash_out_2; // @[sha3.scala 82:21:example.TestHarness.Sha3RocketConfig.fir@135936.4] - wire [63:0] dpath_io_hash_out_3; // @[sha3.scala 82:21:example.TestHarness.Sha3RocketConfig.fir@135936.4] - wire [1:0] _T; // @[:example.TestHarness.Sha3RocketConfig.fir@135941.4] - wire [63:0] _GEN_0; // @[sha3.scala 85:24:example.TestHarness.Sha3RocketConfig.fir@135942.4] - wire [63:0] _GEN_1; // @[sha3.scala 85:24:example.TestHarness.Sha3RocketConfig.fir@135942.4] - wire [63:0] _GEN_2; // @[sha3.scala 85:24:example.TestHarness.Sha3RocketConfig.fir@135942.4] - CtrlModule ctrl ( // @[sha3.scala 61:20:example.TestHarness.Sha3RocketConfig.fir@135916.4] - .clock(ctrl_clock), - .reset(ctrl_reset), - .io_rocc_req_val(ctrl_io_rocc_req_val), - .io_rocc_req_rdy(ctrl_io_rocc_req_rdy), - .io_rocc_funct(ctrl_io_rocc_funct), - .io_rocc_rs1(ctrl_io_rocc_rs1), - .io_rocc_rs2(ctrl_io_rocc_rs2), - .io_busy(ctrl_io_busy), - .io_dmem_req_val(ctrl_io_dmem_req_val), - .io_dmem_req_rdy(ctrl_io_dmem_req_rdy), - .io_dmem_req_tag(ctrl_io_dmem_req_tag), - .io_dmem_req_addr(ctrl_io_dmem_req_addr), - .io_dmem_req_cmd(ctrl_io_dmem_req_cmd), - .io_dmem_resp_val(ctrl_io_dmem_resp_val), - .io_dmem_resp_tag(ctrl_io_dmem_resp_tag), - .io_dmem_resp_data(ctrl_io_dmem_resp_data), - .io_round(ctrl_io_round), - .io_absorb(ctrl_io_absorb), - .io_aindex(ctrl_io_aindex), - .io_init(ctrl_io_init), - .io_write(ctrl_io_write), - .io_windex(ctrl_io_windex), - .io_buffer_out(ctrl_io_buffer_out) - ); - DpathModule dpath ( // @[sha3.scala 82:21:example.TestHarness.Sha3RocketConfig.fir@135936.4] - .clock(dpath_clock), - .reset(dpath_reset), - .io_absorb(dpath_io_absorb), - .io_init(dpath_io_init), - .io_write(dpath_io_write), - .io_round(dpath_io_round), - .io_aindex(dpath_io_aindex), - .io_message_in(dpath_io_message_in), - .io_hash_out_0(dpath_io_hash_out_0), - .io_hash_out_1(dpath_io_hash_out_1), - .io_hash_out_2(dpath_io_hash_out_2), - .io_hash_out_3(dpath_io_hash_out_3) + Sha3Accel sha3 ( + .clock(clock), + .reset(reset), + .io_cmd_ready(io_cmd_ready), + .io_cmd_valid(io_cmd_valid), + .io_cmd_bits_inst_funct(io_cmd_bits_inst_funct), + .io_cmd_bits_rs1(io_cmd_bits_rs1), + .io_cmd_bits_rs2(io_cmd_bits_rs2), + .io_mem_req_ready(io_mem_req_ready), + .io_mem_req_valid(io_mem_req_valid), + .io_mem_req_bits_addr(io_mem_req_bits_addr), + .io_mem_req_bits_tag(io_mem_req_bits_tag), + .io_mem_req_bits_cmd(io_mem_req_bits_cmd), + .io_mem_req_bits_data(io_mem_req_bits_data), + .io_mem_resp_valid(io_mem_resp_valid), + .io_mem_resp_bits_tag(io_mem_resp_bits_tag), + .io_mem_resp_bits_data(io_mem_resp_bits_data), + .io_busy(io_busy) ); ExampleDCO dco ( .col_sel_b(col_sel_b), @@ -112,35 +52,6 @@ module Sha3AccelwBB( // @[:example.TestHarness.Sha3RocketConfig.fir@135905.2] .sleep_b(sleep_b), .clock(dco_clock) ); - assign _T = ctrl_io_windex[1:0]; // @[:example.TestHarness.Sha3RocketConfig.fir@135941.4] - assign _GEN_0 = dpath_io_hash_out_0; // @[sha3.scala 85:24:example.TestHarness.Sha3RocketConfig.fir@135942.4] - assign _GEN_1 = 2'h1 == _T ? dpath_io_hash_out_1 : _GEN_0; // @[sha3.scala 85:24:example.TestHarness.Sha3RocketConfig.fir@135942.4] - assign _GEN_2 = 2'h2 == _T ? dpath_io_hash_out_2 : _GEN_1; // @[sha3.scala 85:24:example.TestHarness.Sha3RocketConfig.fir@135942.4] - assign io_cmd_ready = ctrl_io_rocc_req_rdy; // @[sha3.scala 64:16:example.TestHarness.Sha3RocketConfig.fir@135921.4] - assign io_mem_req_valid = ctrl_io_dmem_req_val; // @[sha3.scala 71:20:example.TestHarness.Sha3RocketConfig.fir@135927.4] - assign io_mem_req_bits_addr = {{8'd0}, ctrl_io_dmem_req_addr}; // @[sha3.scala 74:24:example.TestHarness.Sha3RocketConfig.fir@135930.4] - assign io_mem_req_bits_tag = {{1'd0}, ctrl_io_dmem_req_tag}; // @[sha3.scala 73:23:example.TestHarness.Sha3RocketConfig.fir@135929.4] - assign io_mem_req_bits_cmd = ctrl_io_dmem_req_cmd; // @[sha3.scala 75:23:example.TestHarness.Sha3RocketConfig.fir@135931.4] - assign io_mem_req_bits_data = 2'h3 == _T ? dpath_io_hash_out_3 : _GEN_2; // @[sha3.scala 85:24:example.TestHarness.Sha3RocketConfig.fir@135942.4] - assign io_busy = ctrl_io_busy; // @[sha3.scala 69:11:example.TestHarness.Sha3RocketConfig.fir@135926.4] - assign ctrl_clock = clock; // @[:example.TestHarness.Sha3RocketConfig.fir@135918.4] - assign ctrl_reset = reset; // @[:example.TestHarness.Sha3RocketConfig.fir@135919.4] - assign ctrl_io_rocc_req_val = io_cmd_valid; // @[sha3.scala 63:26:example.TestHarness.Sha3RocketConfig.fir@135920.4] - assign ctrl_io_rocc_funct = io_cmd_bits_inst_funct[1:0]; // @[sha3.scala 65:26:example.TestHarness.Sha3RocketConfig.fir@135922.4] - assign ctrl_io_rocc_rs1 = io_cmd_bits_rs1; // @[sha3.scala 66:26:example.TestHarness.Sha3RocketConfig.fir@135923.4] - assign ctrl_io_rocc_rs2 = io_cmd_bits_rs2; // @[sha3.scala 67:26:example.TestHarness.Sha3RocketConfig.fir@135924.4] - assign ctrl_io_dmem_req_rdy = io_mem_req_ready; // @[sha3.scala 72:26:example.TestHarness.Sha3RocketConfig.fir@135928.4] - assign ctrl_io_dmem_resp_val = io_mem_resp_valid; // @[sha3.scala 78:26:example.TestHarness.Sha3RocketConfig.fir@135933.4] - assign ctrl_io_dmem_resp_tag = io_mem_resp_bits_tag[6:0]; // @[sha3.scala 79:26:example.TestHarness.Sha3RocketConfig.fir@135934.4] - assign ctrl_io_dmem_resp_data = io_mem_resp_bits_data; // @[sha3.scala 80:26:example.TestHarness.Sha3RocketConfig.fir@135935.4] - assign dpath_clock = clock; // @[:example.TestHarness.Sha3RocketConfig.fir@135938.4] - assign dpath_reset = reset; // @[:example.TestHarness.Sha3RocketConfig.fir@135939.4] - assign dpath_io_absorb = ctrl_io_absorb; // @[sha3.scala 88:19:example.TestHarness.Sha3RocketConfig.fir@135943.4] - assign dpath_io_init = ctrl_io_init; // @[sha3.scala 89:17:example.TestHarness.Sha3RocketConfig.fir@135944.4] - assign dpath_io_write = ctrl_io_write; // @[sha3.scala 90:18:example.TestHarness.Sha3RocketConfig.fir@135945.4] - assign dpath_io_round = ctrl_io_round; // @[sha3.scala 91:18:example.TestHarness.Sha3RocketConfig.fir@135946.4] - assign dpath_io_aindex = ctrl_io_aindex; // @[sha3.scala 93:19:example.TestHarness.Sha3RocketConfig.fir@135948.4] - assign dpath_io_message_in = ctrl_io_buffer_out; // @[sha3.scala 84:23:example.TestHarness.Sha3RocketConfig.fir@135940.4] endmodule module ExampleDCO ( From ddb4676ddfedcf7af99d75dfa4c7abfd9a2ec94a Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Fri, 27 Sep 2019 10:39:07 -0700 Subject: [PATCH 32/39] update with tethered v standalone | small flow fixes [ci skip] --- docs/Advanced-Usage/Chip-Communication.rst | 29 +++++++++++++--------- docs/Software/Spike.rst | 17 ++++++++++++- 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/docs/Advanced-Usage/Chip-Communication.rst b/docs/Advanced-Usage/Chip-Communication.rst index 31a55007..ec17377b 100644 --- a/docs/Advanced-Usage/Chip-Communication.rst +++ b/docs/Advanced-Usage/Chip-Communication.rst @@ -3,8 +3,13 @@ Communicating with the Chip/DUT =============================== -What good is a chip/DUT if it can't communicate with the outside world? Chipyard designs -communicate to the outside world in one of two ways: +What good is a chip/DUT if it can't communicate with the outside world? There are two types of designs that can be +made: tethered or standalone designs. A tethered design is where a host must interact with the DUT (a target) to bringup the design. +A standalone design is a design that can bringup itself (has its own bootrom, loads programs itself, etc). An example of a tethered design +is a Chipyard simulation where the host computer loads the test program into the designs memory. An example of a standalone design is +a design where a program can be loaded from an SDCard by default. + +Chipyard designs communicate to the outside world in one of two ways that mainly correspond to a tethered design: * using the Tethered Serial Interface (TSI) or the Debug Module Interface (DMI) with the Front-End Server (FESVR) to communicate with the design * using the JTAG interface with OpenOCD and GDB to communicate with the design @@ -20,7 +25,7 @@ Primer on the Front-End Server (FESVR) FESVR is a C++ library that manages communication between a host machine and a RISC-V target. For debugging, it provides a simple API to reset, -send messages, and run programs on a DUT but it also provides peripheral device emulation. +send messages, and load/run programs on a DUT but it also provides peripheral device emulation. It can be added used simulators (VCS, Verilator, FireSim) as well as in a bringup sequence for a taped out chip. @@ -32,7 +37,7 @@ Using the Tethered Serial Interface (TSI) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ By default, Chipyard uses the Tethered Serial Interface (TSI) to communicate with the target. -TSI is the implementation of the HTIF interface that is used to send commands to the +TSI is the implementation of the HTIF that is used to send commands to the RISC-V target. These TSI commands are simple R/W commands that are able to probe the DUT's memory space. In simulation, these TSI commands connect to a ``SimSerial`` (located in the ``generators/testchipip`` project) simulation C++ @@ -51,9 +56,9 @@ sends the converted TileLink commands over a serial link to the chip. Using the Debug Module Interface (DMI) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Another option to bringup the target is to use the Debug Module Interface (DMI) provided by Rocket Chip. -In this case, a Debug Test Module (DTM) must exist in the target that communicates with the DMI. -The DTM is given in the RISC-V Debug Specification and is responsible for managing communication between +Another option to bringup the target is to use the Debug Module Interface (DMI) provided by a Debug Transfer Module (DTM) existing within the target. +Similar to TSI, DMI is an implementation of HTIF. +The DTM is given in the `RISC-V Debug Specification `__ and is responsible for managing communication between the target and whatever lives on the other side of the DMI (in this case FESVR). This is added by default to the Rocket Chip ``Subsystem`` by having the ``HasPeripheryDebug`` and ``HasPeripheryDebugModuleImp`` mixins. Chipyard disables the DTM by default so that it can use the TSI interface. @@ -74,7 +79,7 @@ configurations. For example: make CONFIG=LargeBoomConfig run-asm-tests -If you would like to build a DMI system with a Chipyard configuration, the you must create a +If you would like to build and simulate a DMI system with a Chipyard configuration, the you must create a top-level system with the DTM as well as a config to use that top-level system. .. literalinclude:: ../../generators/example/src/main/scala/RocketConfigs.scala @@ -91,12 +96,12 @@ The rest of the mixins specify the rest of the system (cores, accelerators, etc) # or cd sims/vcs - make CONFIG=dmiRocketConfig TOP=TopWithDTM MODEL=TestHarnessWithDTM + make CONFIG=dmiRocketConfig TOP=TopWithDTM MODEL=TestHarnessWithDTM run-asm-tests Using the JTAG Interface ------------------------ -The main way to use JTAG with a Rocket Chip based system is to instantiate the Debug Test Module (DTM) +The main way to use JTAG with a Rocket Chip based system is to instantiate the Debug Transfer Module (DTM) and configure it to use a JTAG interface (by default the DTM is setup to use the DMI interface mentioned above). However, if you want to use JTAG, you must do the following steps to setup a DTM+JTAG enabled system. @@ -116,7 +121,7 @@ The ``WithJtagDTM`` will configure that instantiated DTM to use JTAG as the brin this can be removed if you want a DMI-only bringup). The rest of the mixins specify the rest of the system (cores, accelerators, etc). -Starting the DTM+JTAG Simulation +Building a DTM+JTAG Simulator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ After creating the config, call the ``make`` command like the following: @@ -131,7 +136,7 @@ After creating the config, call the ``make`` command like the following: In this example, this will use the config that you previously specified, as well as set the other parameters that are needed to satisfy the build system. After that point, you -should have a JTAG enabled simulation that you can attach to using OpenOCD and GDB! +should have a JTAG enabled simulator that you can attach to using OpenOCD and GDB! Debugging with JTAG ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/Software/Spike.rst b/docs/Software/Spike.rst index 015ec5b2..50703568 100644 --- a/docs/Software/Spike.rst +++ b/docs/Software/Spike.rst @@ -1,4 +1,19 @@ The RISC-V ISA Simulator (Spike) ================================= -.. attention:: This article is a stub. Fill it out! +Spike is the golden reference functional RISC-V ISA simulator. +It provides full system emulation or proxied emulation with the HTIF/FESVR. +It serves as a starting point for running software on a RISC-V target. +Here is a highlight of some of Spikes main features: + +* Multiple ISAs: RV32IMAFDQCV extensions +* Multiple memory models: Weak Memory Ordering (WMO) and Total Store Ordering (TSO) +* Priveleged Spec: Machine, Supervisor, User modes (v1.11) +* Debug Spec +* Single-step debugging with support for viewing memory/register contents +* Multiple CPU support +* JTAG support +* Highly extensible (add and test new instructions) +* And much more! + +Spike comes pre-packaged in the RISC-V toolchain. From f8a0e5047550f31ab83e39e11f50a74be2bb8245 Mon Sep 17 00:00:00 2001 From: Harrison Liew Date: Fri, 27 Sep 2019 11:56:13 -0700 Subject: [PATCH 33/39] [skip ci] address Abe's comments --- docs/VLSI/Advanced-Usage.rst | 2 +- docs/VLSI/{HAMMER.rst => Hammer.rst} | 10 +++++----- docs/VLSI/Tutorial.rst | 16 ++++++++-------- docs/VLSI/index.rst | 4 ++-- 4 files changed, 16 insertions(+), 16 deletions(-) rename docs/VLSI/{HAMMER.rst => Hammer.rst} (88%) diff --git a/docs/VLSI/Advanced-Usage.rst b/docs/VLSI/Advanced-Usage.rst index 9d0afd76..c7e1bae2 100644 --- a/docs/VLSI/Advanced-Usage.rst +++ b/docs/VLSI/Advanced-Usage.rst @@ -5,7 +5,7 @@ Advanced Usage Alternative RTL Flows --------------------- -The Make-based build system provided supports using Hammer without using RTL generated by Chipyard. To push a custom verilog module through, one only needs to give the following environment variables ``make buildfile`` (or edit them directly in the Makefile). +The Make-based build system provided supports using Hammer without using RTL generated by Chipyard. To push a custom verilog module through, one only needs to append the following environment variables to the ``make buildfile`` command (or edit them directly in the Makefile). .. code-block:: shell diff --git a/docs/VLSI/HAMMER.rst b/docs/VLSI/Hammer.rst similarity index 88% rename from docs/VLSI/HAMMER.rst rename to docs/VLSI/Hammer.rst index 3a7def4b..11d80a07 100644 --- a/docs/VLSI/HAMMER.rst +++ b/docs/VLSI/Hammer.rst @@ -1,12 +1,12 @@ .. _hammer: -Core HAMMER +Core Hammer ================================ -`HAMMER `__ is a physical design generator that wraps around vendor specific technologies and tools to provide a single API to create ASICs. -HAMMER allows for reusability in ASIC design while still providing the designers leeway to make their own modifications. +`Hammer `__ is a physical design generator that wraps around vendor specific technologies and tools to provide a single API to create ASICs. +Hammer allows for reusability in ASIC design while still providing the designers leeway to make their own modifications. -For more information, read the `HAMMER paper `__ and see the `GitHub repository `__ and associated documentation. +For more information, read the `Hammer paper `__ and see the `GitHub repository `__ and associated documentation. Hammer implements a VLSI flow using the following high-level constructs: @@ -28,7 +28,7 @@ Hooks are modifications to steps or actions that are programmatically defined in Configuration (Hammer IR) ========================= -To configure a Hammer flow, supply a set yaml or json configuration files that chooses the tool and technology plugins and versions as well as any design specific configuration options. Collectively, this configuration API is referred to as Hammer IR and can be generated from higher-level abstractions. +To configure a Hammer flow, supply a set ``yaml`` or ``json`` configuration files that chooses the tool and technology plugins and versions as well as any design specific configuration options. Collectively, this configuration API is referred to as Hammer IR and can be generated from higher-level abstractions. The current set of all available Hammer APIs is codified `here `__. diff --git a/docs/VLSI/Tutorial.rst b/docs/VLSI/Tutorial.rst index bab71d4a..40ce3abd 100644 --- a/docs/VLSI/Tutorial.rst +++ b/docs/VLSI/Tutorial.rst @@ -2,7 +2,7 @@ ASAP7 Tutorial ============== -The ``vlsi`` folder of this repository contains an example HAMMER flow with the SHA-3 accelerator and a dummy hard macro. This example tutorial uses the built-in ASAP7 technology plugin and requires access to the included Cadence and Mentor tool plugin submodules. Cadence is necessary for synthesis & place-and-route, while Mentor is needed for DRC & LVS. +The ``vlsi`` folder of this repository contains an example Hammer flow with the SHA-3 accelerator and a dummy hard macro. This example tutorial uses the built-in ASAP7 technology plugin and requires access to the included Cadence and Mentor tool plugin submodules. Cadence is necessary for synthesis & place-and-route, while Mentor is needed for DRC & LVS. Project Structure ----------------- @@ -54,8 +54,8 @@ Prerequisites * Genus, Innovus, and Calibre licenses * For ASAP7 specifically: - * Download the `ASAP7 PDK `__ tarball and do not extract it - * If you have additional ASAP7 hard macros, their LEF & GDS need to be 4x upscaled @ 4000 DBU precision + * Download the `ASAP7 PDK `__ tarball to a directory of choice but do not extract it + * If you have additional ASAP7 hard macros, their LEF & GDS need to be 4x upscaled @ 4000 DBU precision. They may live outside ``extra_libraries`` at your discretion. Initial Setup ------------- @@ -65,7 +65,7 @@ In the Chipyard root, run: ``./scripts/init-vlsi.sh asap7`` -to pull the HAMMER & plugin submodules. Note that for technologies other than ``asap7``, the tech submodule must be added in the ``vlsi`` folder first. +to pull the Hammer & plugin submodules. Note that for technologies other than ``asap7``, the tech submodule must be added in the ``vlsi`` folder first. Pull the Hammer environment into the shell: @@ -77,7 +77,7 @@ Pull the Hammer environment into the shell: Building the Design ------------------- -To elaborate the Sha3RocketConfig (Rocketchip w/ the accelerator) and set up all prerequisites for the build system to push just the accelerator + hard macro through the flow: +To elaborate the ``Sha3RocketConfig`` (Rocket Chip w/ the accelerator) and set up all prerequisites for the build system to push just the accelerator + hard macro through the flow: .. code-block:: shell @@ -85,7 +85,7 @@ To elaborate the Sha3RocketConfig (Rocketchip w/ the accelerator) and set up all The ``MACROCOMPILER_MODE='--mode synflops'`` is needed because the ASAP7 process does not yet have a memory compiler. Therefore, flip-flop arrays are used instead. -The ``CONFIG=Sha3RocketConfig`` selects the target generator config in the same manner as the rest of the Chipyard framework. This elaborates a Rocket-chip with the Sha3Accel module. +The ``CONFIG=Sha3RocketConfig`` selects the target generator config in the same manner as the rest of the Chipyard framework. This elaborates a Rocket Chip with the Sha3Accel module. The ``VLSI_TOP=Sha3AccelwBB`` indicates that we are only interested in physical design of the accelerator block. If this variable is not set, the entire SoC will be pushed through physical design. Note that you should not set the ``TOP`` variable because it is used during Chisel elaboration. @@ -96,7 +96,7 @@ Running the VLSI Flow example-vlsi ^^^^^^^^^^^^ -This is the entry script with placeholders for hooks. In the ``ExampleDriver`` class, a list of hooks is passed in the ``get_extra_par_hooks``. Hooks are additional snippets of python and TCL (via ``x.append()``) to extend the Hammer APIs. Hooks can be inserted using the ``make_pre/post/replacement_hook`` methods. +This is the entry script with placeholders for hooks. In the ``ExampleDriver`` class, a list of hooks is passed in the ``get_extra_par_hooks``. Hooks are additional snippets of python and TCL (via ``x.append()``) to extend the Hammer APIs. Hooks can be inserted using the ``make_pre/post/replacement_hook`` methods as shown in this example. Refer to the Hammer documentation on hooks for a detailed description of how these are injected into the VLSI flow. example.yml ^^^^^^^^^^^ @@ -110,7 +110,7 @@ Synthesis ``make syn`` -Post-synthesis logs and collateral are in ``build/syn-rundir``. The Raw QoR data is available at ``build/syn-rundir/reports``, and methods to extract this information for design space exploration are a WIP. +Post-synthesis logs and collateral are in ``build/syn-rundir``. The raw QoR data is available at ``build/syn-rundir/reports``, and methods to extract this information for design space exploration are a WIP. Place-and-Route ^^^^^^^^^^^^^^^ diff --git a/docs/VLSI/index.rst b/docs/VLSI/index.rst index 8bc98b60..0f5d32d5 100644 --- a/docs/VLSI/index.rst +++ b/docs/VLSI/index.rst @@ -2,13 +2,13 @@ VLSI Flow ================================ The Chipyard framework aims to provide wrappers for a general VLSI flow. -In particular, we aim to support the HAMMER physical design generator flow. +In particular, we aim to support the Hammer physical design generator flow. .. toctree:: :maxdepth: 2 :caption: VLSI Flow: Building-A-Chip - HAMMER + Hammer Tutorial Advanced-Usage From 8f14fae94eb75f79bfcae74f09143a2f4c06f58a Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Fri, 27 Sep 2019 11:56:16 -0700 Subject: [PATCH 34/39] update with changes [ci skip] --- docs/Advanced-Usage/Chip-Communication.rst | 14 +++++++------- docs/Software/Spike.rst | 8 ++++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/Advanced-Usage/Chip-Communication.rst b/docs/Advanced-Usage/Chip-Communication.rst index ec17377b..41b52232 100644 --- a/docs/Advanced-Usage/Chip-Communication.rst +++ b/docs/Advanced-Usage/Chip-Communication.rst @@ -3,13 +3,13 @@ Communicating with the Chip/DUT =============================== -What good is a chip/DUT if it can't communicate with the outside world? There are two types of designs that can be +There are two types of designs that can be made: tethered or standalone designs. A tethered design is where a host must interact with the DUT (a target) to bringup the design. A standalone design is a design that can bringup itself (has its own bootrom, loads programs itself, etc). An example of a tethered design is a Chipyard simulation where the host computer loads the test program into the designs memory. An example of a standalone design is a design where a program can be loaded from an SDCard by default. -Chipyard designs communicate to the outside world in one of two ways that mainly correspond to a tethered design: +There are two ways the outside world (or host) can communicate with a tethered Chipyard design: * using the Tethered Serial Interface (TSI) or the Debug Module Interface (DMI) with the Front-End Server (FESVR) to communicate with the design * using the JTAG interface with OpenOCD and GDB to communicate with the design @@ -25,8 +25,8 @@ Primer on the Front-End Server (FESVR) FESVR is a C++ library that manages communication between a host machine and a RISC-V target. For debugging, it provides a simple API to reset, -send messages, and load/run programs on a DUT but it also provides peripheral device emulation. -It can be added used simulators (VCS, Verilator, FireSim) as well as in a bringup sequence +send messages, and load/run programs on a DUT. It also emulates peripheral devices. +It can be incorporated with simulators (VCS, Verilator, FireSim), or used in a bringup sequence for a taped out chip. Specifically, FESVR uses the Host Target Interface (HTIF), a communication bus for the hardware, @@ -37,7 +37,7 @@ Using the Tethered Serial Interface (TSI) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ By default, Chipyard uses the Tethered Serial Interface (TSI) to communicate with the target. -TSI is the implementation of the HTIF that is used to send commands to the +TSI is an implementation of HTIF that is used to send commands to the RISC-V target. These TSI commands are simple R/W commands that are able to probe the DUT's memory space. In simulation, these TSI commands connect to a ``SimSerial`` (located in the ``generators/testchipip`` project) simulation C++ @@ -45,9 +45,9 @@ class that is added to simulation. This ``SimSerial`` device sends the TSI comma the DUT which contains a ``SerialAdapter`` (located in the ``generators/testchipip`` project) that converts the TSI commands to TileLink requests. In simulation, FESVR resets the DUT, and writes into memory the test program. This is currently the fastest -mechanism to simulate the DUT. +mechanism to communicate with the DUT in simulation. -In the case of a chip tapeout bringup, TSI commands can be sent over a modified communication +In the case of a chip tapeout bringup, TSI commands can be sent over a custom communication medium to communicate with the chip. For example, some Berkeley tapeouts have a FPGA with a RISC-V soft-core that runs FESVR. The FESVR on the soft-core sends TSI commands to a TSI to TileLink converter living on the FPGA (i.e. ``SerialAdapter``). Then this converter diff --git a/docs/Software/Spike.rst b/docs/Software/Spike.rst index 50703568..23b7b557 100644 --- a/docs/Software/Spike.rst +++ b/docs/Software/Spike.rst @@ -1,19 +1,19 @@ The RISC-V ISA Simulator (Spike) ================================= -Spike is the golden reference functional RISC-V ISA simulator. +Spike is the golden reference functional RISC-V ISA C++ sofware simulator. It provides full system emulation or proxied emulation with the HTIF/FESVR. It serves as a starting point for running software on a RISC-V target. Here is a highlight of some of Spikes main features: * Multiple ISAs: RV32IMAFDQCV extensions * Multiple memory models: Weak Memory Ordering (WMO) and Total Store Ordering (TSO) -* Priveleged Spec: Machine, Supervisor, User modes (v1.11) +* Privileged Spec: Machine, Supervisor, User modes (v1.11) * Debug Spec * Single-step debugging with support for viewing memory/register contents * Multiple CPU support * JTAG support * Highly extensible (add and test new instructions) -* And much more! -Spike comes pre-packaged in the RISC-V toolchain. +Spike comes pre-packaged in the RISC-V toolchain and is available on the path as ``spike``. +More information can be found in the `Spike repository `__. From bbe457d14dc9540d735c54edceeca5c4052e0edd Mon Sep 17 00:00:00 2001 From: Harrison Liew Date: Fri, 27 Sep 2019 17:42:35 -0700 Subject: [PATCH 35/39] Turn the GDS scaling into a new hook --- docs/VLSI/Tutorial.rst | 2 ++ vlsi/example-vlsi | 22 +++++++++++++++++++++- vlsi/hammer | 2 +- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/docs/VLSI/Tutorial.rst b/docs/VLSI/Tutorial.rst index 40ce3abd..7c2e0d2f 100644 --- a/docs/VLSI/Tutorial.rst +++ b/docs/VLSI/Tutorial.rst @@ -98,6 +98,8 @@ example-vlsi ^^^^^^^^^^^^ This is the entry script with placeholders for hooks. In the ``ExampleDriver`` class, a list of hooks is passed in the ``get_extra_par_hooks``. Hooks are additional snippets of python and TCL (via ``x.append()``) to extend the Hammer APIs. Hooks can be inserted using the ``make_pre/post/replacement_hook`` methods as shown in this example. Refer to the Hammer documentation on hooks for a detailed description of how these are injected into the VLSI flow. +The ``scale_final_gds`` hook is a particularly powerful hook. It dumps a Python script provided by the ASAP7 tech plugin, an executes it within the Innovus TCL interpreter. This hook is run after ``write_design`` because the ASAP7 PDK requires post-par GDSs to be scaled down by a factor of 4. + example.yml ^^^^^^^^^^^ This contains the Hammer configuration for this example project. Example clock constraints, power straps definitions, placement constraints, and pin constraints are given. Additional configuration for the extra libraries and tools are at the bottom. diff --git a/vlsi/example-vlsi b/vlsi/example-vlsi index 5d43f8c5..a17f4f0c 100755 --- a/vlsi/example-vlsi +++ b/vlsi/example-vlsi @@ -1,4 +1,5 @@ #!/usr/bin/env python3 +import os import hammer_vlsi from hammer_vlsi import CLIDriver, HammerToolHookAction @@ -26,6 +27,22 @@ def example_tool_settings(x: hammer_vlsi.HammerTool) -> bool: ''') return True +def scale_final_gds(x: hammer_vlsi.HammerTool) -> bool: + """ + Scale the final GDS by a factor of 4 + """ + x.append(''' +# Write script out to a temporary file and execute it +set fp [open "{script_file}" "w"] +puts -nonewline $fp "{script_text}" +close $fp +if {{ [catch {{ exec python3 {script_file} }} msg] }} {{ + puts "$::errorInfo" +}} +'''.format(script_text=x.technology.scale_gds_script(x.output_gds_filename), script_file=os.path.join(x.run_dir, "gds_scale.py"))) + return True + + class ExampleDriver(CLIDriver): def get_extra_par_hooks(self) -> List[HammerToolHookAction]: extra_hooks = [ @@ -39,8 +56,11 @@ class ExampleDriver(CLIDriver): # make_replacement_hook will replace the specified step with a custom hook hammer_vlsi.HammerTool.make_replacement_hook("place_tap_cells", example_place_tap_cells), # make_removal_hook will remove the specified step from the flow - hammer_vlsi.HammerTool.make_removal_hook("place_bumps") + hammer_vlsi.HammerTool.make_removal_hook("place_bumps"), # The target step in any of the above calls may be a default step or another one of your custom hooks + + # This is an example of a technology-supplied hook (look in hammer/src/hammer-vlsi/technology/asap7/__init__.py) + hammer_vlsi.HammerTool.make_post_insertion_hook("write_design", scale_final_gds) ] return extra_hooks diff --git a/vlsi/hammer b/vlsi/hammer index 946c4f41..1b07b9a3 160000 --- a/vlsi/hammer +++ b/vlsi/hammer @@ -1 +1 @@ -Subproject commit 946c4f416709663651580f7c4c1be2e2652dff6f +Subproject commit 1b07b9a378c2936389b95f7ee1436e1f492d55e2 From 4873fea4ceab9fbf1977213d21e1a9ed854251de Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Fri, 27 Sep 2019 20:02:12 -0700 Subject: [PATCH 36/39] update chip communication with pictures | update spike [ci skip] --- docs/Advanced-Usage/Chip-Communication.rst | 111 ++++++++++++--------- docs/Software/Spike.rst | 6 +- docs/_static/images/chip-bringup.png | Bin 0 -> 18259 bytes docs/_static/images/chip-communication.png | Bin 0 -> 106042 bytes 4 files changed, 70 insertions(+), 47 deletions(-) create mode 100644 docs/_static/images/chip-bringup.png create mode 100644 docs/_static/images/chip-communication.png diff --git a/docs/Advanced-Usage/Chip-Communication.rst b/docs/Advanced-Usage/Chip-Communication.rst index 41b52232..60fe22ad 100644 --- a/docs/Advanced-Usage/Chip-Communication.rst +++ b/docs/Advanced-Usage/Chip-Communication.rst @@ -1,75 +1,95 @@ .. _chip-communication: -Communicating with the Chip/DUT +Communicating with the DUT =============================== -There are two types of designs that can be -made: tethered or standalone designs. A tethered design is where a host must interact with the DUT (a target) to bringup the design. -A standalone design is a design that can bringup itself (has its own bootrom, loads programs itself, etc). An example of a tethered design -is a Chipyard simulation where the host computer loads the test program into the designs memory. An example of a standalone design is -a design where a program can be loaded from an SDCard by default. +There are two types of DUTs that can be made: `tethered` or `standalone` DUTs. +A `tethered` DUT is where a host computer (or just host) must send transactions to the DUT to bringup a program. +This differs from a `standalone` DUT that can bringup itself (has its own bootrom, loads programs itself, etc). +An example of a tethered DUT is a Chipyard simulation where the host loads the test program into the DUTs memory and signals to the DUT that the program is ready to run. +An example of a standalone DUT is a Chipyard simulation where a program can be loaded from an SDCard by default. +In this section, we mainly describe how to communicate to tethered DUTs. -There are two ways the outside world (or host) can communicate with a tethered Chipyard design: +There are two ways the host (otherwise known as the outside world) can communicate with a tethered Chipyard DUT: -* using the Tethered Serial Interface (TSI) or the Debug Module Interface (DMI) with the Front-End Server (FESVR) to communicate with the design -* using the JTAG interface with OpenOCD and GDB to communicate with the design +* Using the Tethered Serial Interface (TSI) or the Debug Module Interface (DMI) with the Front-End Server (FESVR) to communicate with the DUT +* Using the JTAG interface with OpenOCD and GDB to communicate with the DUT + +The following picture shows a block diagram view of all the supported communication mechanisms +split between the host and the simulation. + +.. image:: ../_static/images/chip-communication.png Using the Tethered Serial Interface (TSI) or the Debug Module Interface (DMI) ----------------------------------------------------------------------------- -If you are using TSI or the DMI to communicate with the target (DUT/chip), you are using -the Front-End Server (FESVR) to facilitate communication between the host machine and the target. +If you are using TSI or DMI to communicate with the DUT, you are using +the Front-End Server (FESVR) to facilitate communication between the host and the DUT. Primer on the Front-End Server (FESVR) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ FESVR is a C++ library that manages communication -between a host machine and a RISC-V target. For debugging, it provides a simple API to reset, +between a host machine and a RISC-V DUT. For debugging, it provides a simple API to reset, send messages, and load/run programs on a DUT. It also emulates peripheral devices. It can be incorporated with simulators (VCS, Verilator, FireSim), or used in a bringup sequence for a taped out chip. -Specifically, FESVR uses the Host Target Interface (HTIF), a communication bus for the hardware, -to speak with the target. HTIF is a non-standard Berkeley extension that uses a FIFO non-blocking -interface to communicate with the target. +Specifically, FESVR uses the Host Target Interface (HTIF), a communication protocol, +to speak with the DUT. HTIF is a non-standard Berkeley protocol that uses a FIFO non-blocking +interface to communicate with the DUT. It defines a protocol where you can read/write memory, +load/start/stop the program, and more. Both TSI and DMI implement this HTIF protocol differently +in order to communicate with the DUT. Using the Tethered Serial Interface (TSI) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -By default, Chipyard uses the Tethered Serial Interface (TSI) to communicate with the target. -TSI is an implementation of HTIF that is used to send commands to the -RISC-V target. These TSI commands are simple R/W commands -that are able to probe the DUT's memory space. In simulation, these TSI commands connect -to a ``SimSerial`` (located in the ``generators/testchipip`` project) simulation C++ -class that is added to simulation. This ``SimSerial`` device sends the TSI command to -the DUT which contains a ``SerialAdapter`` (located in the ``generators/testchipip`` -project) that converts the TSI commands to TileLink requests. In simulation, FESVR -resets the DUT, and writes into memory the test program. This is currently the fastest +By default, Chipyard uses the Tethered Serial Interface (TSI) to communicate with the DUT. +TSI protocol is an implementation of HTIF that is used to send commands to the +RISC-V DUT. These TSI commands are simple R/W commands +that are able to probe the DUT's memory space. During simulation, the host sends TSI commands to a +simulation stub called ``SimSerial`` (C++ class) that resides in a ``SimSerial`` verilog module +(both are located in the ``generators/testchipip`` project). This ``SimSerial`` verilog module then +sends the TSI command recieved by the simulation stub into the DUT which then converts the TSI +command into a TileLink request. This conversion is done by the ``SerialAdapter`` module +(located in the ``generators/testchipip`` project). In simulation, FESVR +resets the DUT, writes into memory the test program, and indicates to the DUT to start the program +through an interrupt (see :ref:`Chipyard Boot Process`). Using TSI is currently the fastest mechanism to communicate with the DUT in simulation. In the case of a chip tapeout bringup, TSI commands can be sent over a custom communication medium to communicate with the chip. For example, some Berkeley tapeouts have a FPGA with a RISC-V soft-core that runs FESVR. The FESVR on the soft-core sends TSI commands to a TSI to TileLink converter living on the FPGA (i.e. ``SerialAdapter``). Then this converter -sends the converted TileLink commands over a serial link to the chip. +sends the converted TileLink commands over a serial link to the chip. The following image shows this flow: + +.. image:: ../_static/images/chip-bringup.png Using the Debug Module Interface (DMI) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Another option to bringup the target is to use the Debug Module Interface (DMI) provided by a Debug Transfer Module (DTM) existing within the target. -Similar to TSI, DMI is an implementation of HTIF. -The DTM is given in the `RISC-V Debug Specification `__ and is responsible for managing communication between -the target and whatever lives on the other side of the DMI (in this case FESVR). This is added by default -to the Rocket Chip ``Subsystem`` by having the ``HasPeripheryDebug`` and ``HasPeripheryDebugModuleImp`` mixins. -Chipyard disables the DTM by default so that it can use the TSI interface. -This is because the DTM executes a small loop of code to write the test binary byte-wise into memory -while the default ``SimSerial``/``SerialAdapter``/TSI interface directly writes to memory. +Another option to interface with the DUT is to use the Debug Module Interface (DMI). +Similar to TSI, the DMI protocol is an implementation of HTIF. +In order to communicate with the DUT with the DMI protocol, the DUT needs to contain a Debug Transfer Module (DTM). +The DTM is given in the `RISC-V Debug Specification `__ +and is responsible for managing communication between the DUT and whatever lives on the other side of the DMI (in this case FESVR). +This is implemented in the Rocket Chip ``Subsystem`` by having the ``HasPeripheryDebug`` and ``HasPeripheryDebugModuleImp`` mixins. + During simulation, the host sends DMI commands to a +simulation stub called ``SimDTM`` (C++ class) that resides in a ``SimDTM`` verilog module +(both are located in the ``generators/rocket-chip`` project). This ``SimDTM`` verilog module then +sends the DMI command recieved by the simulation stub into the DUT which then converts the DMI +command into a TileLink request. This conversion is done by the DTM named ``DebugModule`` in the ``generators/rocket-chip`` project. +When the DTM receives the program to load, it starts to write the binary byte-wise into memory. +This is considerably slower than the TSI protocol communication pipeline (i.e. ``SimSerial``/``SerialAdapter``/TileLink) +which directly writes the program binary to memory. +Thus, Chipyard removes the DTM by default in favor of the TSI protocol for DUT communication. Starting the TSI or DMI Simulation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Since Chipyard uses TSI by default, you can run a TSI based simulation by running any of the default -configurations. For example: +All default Chipyard configurations use TSI to communicate between the simulation and the simulated SoC/DUT. Hence, when running a +software RTL simulation, as is indicated in the :ref:`Software RTL Simulation` section, you are in-fact using TSI to communicate with the DUT. As a +reminder, to run a software RTL simulation, run: .. code-block:: bash @@ -79,16 +99,17 @@ configurations. For example: make CONFIG=LargeBoomConfig run-asm-tests -If you would like to build and simulate a DMI system with a Chipyard configuration, the you must create a -top-level system with the DTM as well as a config to use that top-level system. +If you would like to build and simulate a Chipyard configuration with a DTM configured for DMI communication, then you must create a +top-level system with the DTM (``TopWithDTM``), a test-harness to connect to the DTM (``TestHarnessWithDTM``), as well as a config to use that top-level system. .. literalinclude:: ../../generators/example/src/main/scala/RocketConfigs.scala :language: scala :start-after: DOC include start: DmiRocket :end-before: DOC include end: DmiRocket -In this example, the ``WithDTMTop`` mixin specifies that the top-level SoC will instantiate a DTM. +In this example, the ``WithDTMTop`` mixin specifies that the top-level SoC will instantiate a DTM (that by default is setup to use DMI). The rest of the mixins specify the rest of the system (cores, accelerators, etc). +Then you can run simulations with the new DMI-enabled top-level and test-harness. .. code-block:: bash @@ -103,28 +124,26 @@ Using the JTAG Interface The main way to use JTAG with a Rocket Chip based system is to instantiate the Debug Transfer Module (DTM) and configure it to use a JTAG interface (by default the DTM is setup to use the DMI interface mentioned above). -However, if you want to use JTAG, you must do the following steps to setup a DTM+JTAG enabled system. Creating a DTM+JTAG Config ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ First, a DTM config must be created for the system that you want to create. -This involves specifying the SoC top-level to add a DTM as well as configuring that DTM to use JTAG. +This step is similar to the DMI simulation section within the :ref:`Starting the TSI or DMI Simulation` section. +First, you must make a top-level system (``TopWithDTM``) and test-harness (``TestHarnessWithDTM``) that instantiates +and connects the DTM correctly. The configuration is very similar to a DMI-based configuration. The main difference +is the addition of the ``WithJtagDTM`` mixin that configures the instantiated DTM to use the JTAG protocol as the +bringup method. .. literalinclude:: ../../generators/example/src/main/scala/RocketConfigs.scala :language: scala :start-after: DOC include start: JtagRocket :end-before: DOC include end: JtagRocket -In this example, the ``WithDTMTop`` mixin specifies that the top-level SoC will instantiate a DTM. -The ``WithJtagDTM`` will configure that instantiated DTM to use JTAG as the bringup method (note: -this can be removed if you want a DMI-only bringup). -The rest of the mixins specify the rest of the system (cores, accelerators, etc). - Building a DTM+JTAG Simulator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -After creating the config, call the ``make`` command like the following: +After creating the config, call the ``make`` command like the following to build a simulator for your RTL: .. code-block:: bash diff --git a/docs/Software/Spike.rst b/docs/Software/Spike.rst index 23b7b557..5c022471 100644 --- a/docs/Software/Spike.rst +++ b/docs/Software/Spike.rst @@ -2,7 +2,7 @@ The RISC-V ISA Simulator (Spike) ================================= Spike is the golden reference functional RISC-V ISA C++ sofware simulator. -It provides full system emulation or proxied emulation with the HTIF/FESVR. +It provides full system emulation or proxied emulation with `HTIF/FESVR `__. It serves as a starting point for running software on a RISC-V target. Here is a highlight of some of Spikes main features: @@ -15,5 +15,9 @@ Here is a highlight of some of Spikes main features: * JTAG support * Highly extensible (add and test new instructions) +In most cases, software development for a Chipyard target will begin with functional simulation using Spike +(usually with the addition of custom Spike models for custom accelerator functions), and only later move on to +full cycle-accurate simulation using software RTL simulators or FireSim. + Spike comes pre-packaged in the RISC-V toolchain and is available on the path as ``spike``. More information can be found in the `Spike repository `__. diff --git a/docs/_static/images/chip-bringup.png b/docs/_static/images/chip-bringup.png new file mode 100644 index 0000000000000000000000000000000000000000..b7ed022648969b8749a642e1d2f5c66a377a1823 GIT binary patch literal 18259 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 MRAuuYJq!H506YynlmGw# literal 0 HcmV?d00001 diff --git a/docs/_static/images/chip-communication.png b/docs/_static/images/chip-communication.png new file mode 100644 index 0000000000000000000000000000000000000000..4492bd8b81af70ccdc0f89642fb7a6da00800904 GIT binary patch literal 106042 zcmeEu2T+txuqU7hf}kKlM3O{-WhLhzNRXU!lCWf!oTG{$StLgh$w^?zu%HMiu%so! z0!q%3VM+I4_=i{TuCD5;t}Z;QTzAL$dS-gMd%Az!^Sx44mL??>rQfdt{52jw=e%3cA z#m!FizOIrgtrXP7l9rc)hvVUWF+5sYS`iluh>-eYnct5CzeMj_ySX_Dfx(`ho*bUs z98ec4FsGoPAow8{n2QSp^Z>bfJGwpf0y(9xG z(fju=2m0&JuX(!JK>i-d(e?MTfCYjt{|C&;@euqMZQxOn%T^(EOIN79`z3iTM;kXW zE|H&||6}vtqy2hH3hLnGV(ID%JSN8b`;mXP{m1?)E;g3H`YwkN|4i_|-{Ute5%49u{=vRqd-Jmu*c>rD5%6CdEr$1Uu#5o% zLjvQ;<42lanCmDUKa%#DPUpDT7sSN+xXp)5RPVzc`H)NBdL(g6Rl?7jHSpFg%J%4Y zv{A_#vF9yKAogYT=2?p1mCN3jkIWjjMo@4sJ)FNEB*8_BJ3~?P z&abT?ENx`l`{YEl(#F{I)%_90!QZ`uTK#YTfJ3dmKfWAH7zdF+jjq)P~?6BVE1aq!-lMW68z( zi+O*DAK=|e9$$N6_lHYAi3fFKU4?MGQN#Qffe$(W0b>&{Li1lNxVlbC`><;C&B(twlLTJS z`mN#yWcgm&d0CIIVT=9X82BUPKP&*XQGuf)ss6NF&U{KTC^yp4nPU0sKSj~& zQk0oZ{5zum40owkj&y*MlO+W!|5L|;m;oL2-Wj%9|EG$~k^vg>zex7|-uy@A{R-#= z%m&rq-oe7ES)f{|&KODr()}>o8hk|tg3MELUF=y=4NCew_N|y!Xv^6F%5!F8rsZOJ zASZ>}syBfxY1%2v|6m+ugG{aFFm4iXUmaRrwqDRIH*R)Y8C=Xhi4_3o9L@wn)4z07 zfeq`NX5jv|BQrBC8u`kHPifP!Ft2*Gx)GoA{}?fV65JE$zas%WD|Y%rD)ghs>5n$M z(K24Heaae-jR`{Rbss_J@1H689Sf@0$E(<|V8wb9kA51J*+tW~$Bo1>(thwR!>l>JJ~*Q%b*~8t z2#jj%QwASBdK4}ar5JEOs8y8Iv|~MU$47q7$F;%f+cTMyFZ40MmUL-Zr2}k{*dY}N zJojt%*#{=K;1-6biQZdz!=#kzh-wf7#lGN5V%K}u=MhCn{y_cnjh?vvTg$9iUuA+? z*~bm#uRZ&{{|C5{_XGzcyLiO&s{Ooo7l-eqCbCnD`Hcz4#!!pu15N69xw+dXL)-H=D7Y9hb2{jBd^5uwr>bv~NYDyiXIKXB%=4IbnBkU~v=|?9 zBt6hz0we$}rx-D30-WgPg6|UKvdH0kg9;(|^+Xs_SI}-gpmTTC#rTW#W+*Z-mk%OtqJVk4H z!VW6$cEi<)FeMEJ>##AXDY+}5&r8T$`8pvAjwxV7|Mf`hfL72^m zlr5idhdjlUcVR4Lba&D$?ktdo79{h^I)}CSS^_)Gq?r7+`t{<2$QRSD7pJ=_bL@bA zbH}hcWTL;kriZ|v(S*8ESm`W&Z;vQFkxA8x@8^gB)LSzpTPjq47Xc&VTrH^2cx9&6 z%me3hoU$g+K(NY-ob4f#IE>JZrZ7Fltff?&swQ;aQ9rvPpwc%mAw4}a#7~5`+sRFq zHP}MIYd8UmKV$%jwjE*tF+X&{x^iV-FXOcsATAmzqL!N<%ImqzA&PcX2{RSuosuDV z6pYmxEktCi{?aBR?Xfb^Vq`phasX-Iv=4sI_+!jGCWUGm?%$YK#WS2kPzGyN$h^bc6a#fzQ3w9JnT(s0srv{f6=Ns zb;oBZ!_!TU+s3E625z#Zg0*06hFE!0Zdm{B$wSvl1?bsGL&Hg#NlQQln{7z6Ub{#U zJn9bTC%-4abk2!sC6yYmMkuNp&!6)_dSFhH5yVlS&=#9XCIJIj&SwEbLNZm@r7E$n z#16UIN+F0;3i;78BP6|HWE?g=8P5ur#TQeHRi*A8hF>R;1TksJ~gB}5tMd5rYZs<5%b(kSGXNhc96J(%OH*EVW}9dgLsm)FN~Vv?h+C4 zJy=KPtE7Pw`WNplDxgH|^Ah?M{QE8Et@~mCom|V|1?g!<2l%h$Jn~47n2MDknj%3Rr1y-(cmK-omUzd%KeRB43}+kveTFb_X|{CEt5XsQ|Q z9`Kdsa6+H;tAS32vaWVW6_f@-?vT1iq`DuJn6-y@Of!dnAIc*OV`@;)d`x?M{Z=yL z8$10*4+n?D<%f41qLyzZ>&r#t!9&J^8{pzb3%DY>LJbwcZ z!BxYs$Ncfb(>9n=5~#G0XpPEQ|ErCIwgPmIJcKA&k3W&8%i0H_KZfpn$(zN4g)0a6 zN}2n8tv*?0$8fV-y5e%kPo9>GJt-Raz`g-TzL>v z7wl92QROC+$$L2>(E7}Wr_Uvc%=hqy?}=eFle3N-+U*|mY^Td*rLP7&q-WJ&DWE77 z^G7c$^KIY~tCSwy)Vm1iH%ym$y1Rurw}rE&X2))eV2;ATssO?WvowaKbU>t1+p5Gw zHBv^BSo175#ZkwDs0Q>|*|rf6~X>*L)ee*OL}ONVNU8VEzr?_WWmggOz6 zQ3K48nj0ROu}~^HdaZq;x&O<6Vp2*?;_;S^gDsTLY)ad-X{r{Ql|rKyRP=3ah^{MbWnFjQ*qygou_=;Be4J?SP{S<+@57< zlWLIaxi>uf@p)7TPS=2s^lqLpil-#unvZo}g_qPCDQQAsq@&?TRPV&hSNo4bp%4q( z?f27Pd$0iAzVxBwT(CyY?vTE4+nmzNQoEbef0CEUm}5!bp@8bjb*R{E$EboJZ25|1 zpWl5QHLuDsnYqbtqp`L`W+e$HRyiA0vN$I4*) zy$UkSRW(lZkh%heyYFy*R)8&ajenZPWO3XSX zH`6o^p#YOLx3(^Dr+9yy2ZcW`4)+imkfS=d#vPg?jY# zLFp@UvR(!82G%rN6olYUYw+>unhC`8AIppF8RLHv!^%^*ixf_*xuig*59XX-`T*2(^ zO;n>@j9I8+qp@wJ!U=_va78)-aLn;iSlXShMdT+dNh+cW~tuj zwL0{EkuKW-f%#&qmZA!HV37umq0(nM;6k_?%bOk34^x!nhD;bHGr!TblxxiXPf(}x zhJ+b{M)@QFXZnbjF5nCd7fMJqxD=zWUZC`0bKoV7a%dqACv?10dh0`jf2*HR6*7)6 zrGd@?;8#c0Cldda((&w|HU-fD{X=?|7f9bTBXOHy-{$+A4&;SOk1Wg_HCFmBL)KQt zOC+a`B@zSc>!aDBCPo9H{U`zNjysWoBePs{vLS$C-|P4-`L`r!Z2&Na5wVtdKSVfC zC^uBYE^zuit3u10Mv0@|52Oo}GSX8p!lB8Tt=CGsSPCQ+kT{u3#L8*Ob8OyCIuT@` z4e0hf&;5>Pt$`%7)KwR_a_)ddFvIe_7UdGw#e=cHBK|7s#pZ9wO@fQqRHx&;4`;pL z!$M<0^x0c%juO;54F3H)ClzW_ae8UG&udU3Fzz#4Yt6B->j@)K~T|A7Ynf>>ua zu_%h-T_@V>b~4DAZvTOq{sF9dlCubvl-IUoNr4k`{6ZCt|DtlJ6x6y7S984&Ai4O# zt;Eu-z4w-~c*oYG1_6XDMe3Ka21wTRVHpn$3>+TErxOA{y=JjqCw=NGH4J3550rR~ zm13*8LxATuYxM5Quh5fr_AB6eWcuw>2>%n|stdtTpg?`+>c9R+!7sgw|1L(>+5_Ua zlJO6r$G}tpkm23=;=Zvz*xluNTR~TGd#3)2?EeEy2#(Jb@wx;+so8FMKRBK0+SmDX zfJ5>iwory~=B-3buIcO_2_pm~Y}1K!8OYsC=>%)+CfctI@qeGEm@7Hgd)^&MLpu0j z#DC)|^Ixe2_MbAGn8X0cPOt^XEjYKm^zlnIBL333y@Nwv3uF_Z0VOHa2?sj|${#0# zWsO{}MO^CJtTvXhaZhsnFm^UKF0E4^_Q8$23%3$h;=9xWa#Q9uk5^C!R|f_ZuJ=qG ztoCzW%69NP$F0?c_C=bnXZN|quHHJTZ4IeTyU5rcE&d>vifc!7scNm`xPEn{e7$*y);3?__faT3Ma*SB zu7Cv$1}8*Dhd21IB}yeEyKa;4;*k6%n+)LKp+-(GFPT53M4MZ_g*-c<%&lQJfLw)? zqW9_zM5F0{Swe~L*t%WGUc$DQHjSF)R*kdyRwuRHojV1jud?=6ZhPJHlJmqVq9X0S#u0iVN$;EpU|#p?zeY!)wsw=WMB{S7HgH&w5^G z2-o%`6zeVaJU6Hjf%(=td*q)DW!LRQ>7PFSg-06$*geYb>4YrsGcKmJ%ze#Av)E(x z$G1gP;}S^i`w4)F=eXMuZ2ia-eXb9yyGuR2IIObMwD10KYb1ri;o6~fcOoS@hhK{Uzg80|MLl$Pv9K*PP|!4JaC~Q> z(e0qb1wB$Yx3Pg*4Bnu4X)~TS>w}3UB>>@bPw~OGdJky%=sPUDen|u+P##o=$}TU-L#)1 zb6*?Tg|?Kc${%}2kZ19@6>O@ki3gl6ot@B3H~Y@cf9(*32>JM31SmP_HNSJ5;WH^a z`WD)%m@;ir$*`ZnmCAy=m*MT!J(&Bv<)l}jyU)CnwM8a^tXw(y?c6=Mk%{1rGJkHsYS8Mr%CcvLBx<7C!lfSU9Nw zQT*luaMYzBeU+VEjG`1CEh!u<7^q2Li&6`j?=Ag&ccXBuD1n%!>FAyI4OTMS)6?D5 zPvLg+Hdt5IYV52;eJr-7mGH^$3PO8R7v6B?Zn_HBnTIkhAJ~tX5=^>z(6e$E^ZRWI z(w9D|Z|z9|XNi|5wSe`AW9gnRA_CHcM+NStbLXS=pdB}wBT*_!9|aNot2@7r@Zb|# zASXo=D~JskpxAp?mCuj!4>V6Vma_I8sA8C^cSzXytXDNr(tOT8O#Sl-@CNlemtGPe z?@QS|q0bN#s2g1#7&+AvKeM<7u~m9wA6{~w{yxbkZ*Si;4TmE2IzMka>0E9gYF|vw z7Y>+hO~5C=#^Y#DtuC3ZZ+I5THe=ua7vR1bf)PC4teUF?>^?08-W@vCH;$;x_2F(I zk&vf8dd2Q`{+&JkAbpH%^oNHhf=(DVmg)Y zD>!o$u1*APuMgyuqW6)}R7C{>4l`RV1_mEqJ{|E3b<3`_Q_L8kllGaQsgw)B zo8ST@CO`VlH=dbnz2DA~(-z=jY-WH!KgC5!B8>w+Q@z%@h~OplI3Fssp_h42h+8o9 z_7NVqJjeHt(0{csvDw$o^E38sX4`pbHtiu5(K3DU7XOnCE?&FDB4eW!FF34AP03~n z?NV*KA~@vQ5jELj84*)ne()6RZEtkNz@%@1YEYQ5g zd9L@K@FFZLHOw`2tDpUMCbP~HI1&$g6BB1DXNTzQ+d-4hjmN{?%kPasK(+p7tMYiq5seY zHf~-^MDJEU!A5Ymzyh%64S`4B^1&@4=!K+Ezl&xmP?gSzU(Q+2cvavBx0Nr-8Pg6k z#A)#nh4?On7c(p6#C&#V z8DFw{H9NSx{NkoY3>T99O+`+#o`NrBrl61J+RbY0cUdhhDOOB zAZ5P%GR+vlpRcn3xc+PB?-TFH{^_{_DZTH21Q0LDfPR|5KOe1pKr}wdVuSn3GX8Fs zOUDS-`#x20S)}sI++3bkV?dS}Ldi%#clqP5=2y3AA1b6%R{uiU{y4jnz+m<{@9F-G z^Yi4Obq1#V$~EWTGc!#Cj!TDlo)`b5ip!u3Bomz-ha`VK`RBtP7_2HP?&ZG*0~QTH z1iexEe@_bd7UTd7R--m}>mPFkERg_!(0#5~!~fTMKLBw=51;(qe-B0sXl|kazwN)* zTLTO>F7rg{UxWRFxpGBV=i`+E8$SOrj~~kwjPUk;@FGIl^l3OyDHCz&&Z%)|XM5ep z=F)uNxzmYV!Nw-;!6XQf1`@Qm`v>3qihWrX=WwT7G0RC5a@JqP5#LRIz-rJil&LZ8 zN~Ihmp?({eU|-(WNcqzlNT_6M#arRseMkMy*^RAyKf9j^$Jqef$N6E=)Gp%6p9L?= zh;Y5U2`Y-8CUQ+MJ`n~u!gCdXO$r5E(*s9Ls~Y9mWRD?)f5kVmV)zVx9qVGAk;qFn z9Lm$ae_E>Vo0wrxe=a|E9t2E%xL}@=#H(CcrtuF;B(N?;E$A^3VDUV#!arB?m1RiI z`2EF4N7`0(8U8w4w|~{rh!_ByP*pCTbLm(7wZZ(iyi9|~$E!L$H}rjf%=S|9m(>Sf zG5RBCKu22T;2%FI*>tGGqv4^A@mn*20Vf9<&IdtPz8cYPA0}5rO-_G&6D1V$-X+U= z_%swL#d^GwZx>EpUg^2D7$de?VK)kuF$%okL8N(Z4K5gob`}B#9ut!yPf6I?;b3+6 zM<>nA2f816tg_A)`zw=@bn+C(*|dsA>vtz9xC8>NOR66X{#kpFFg^)b%%?B2O6Df= z{WeII)_i4Yen(xWY*8`Nh%PCUa&o9HNxZs^wCzIbic`CO}xdbmHh++uGim z4nqH}=N2|iK;1!Wu(9_ps@irT zX3cutPx`U%VW#i*SKljcQV2?ga+oyi&GOH{ShQBTs}!A_CZ1t)iyi2~b&Lx$`AV~1 zXMrXQ4C}E*%eTzPG|UjGZNtTZj14y^)ZJHhs`g`3wDD`9vK!+_de6;02-EdGA~`?P zJOS2+56z3U&q{P3JxbXdT%lXQ!C7kX+E%l=`q6fG8Xpx6pMCq$c1yYOSvpZt z(Ti|F9+$O5+m3my!noZG&+`c%+mRAcyHRTY{oz%hMq`jJFp#Fbw!Ep*dUc4Is%Urc z_Eln<8>>32GS^fPFJOckNf!9*q8Nw~OHZX@t?R4=#R`ZTq`5AP7p(b*ySZGQkBp3qq zTo=$PpRNVBG`)TFT#}9s6B2-RyV{O?tadB+Dw(o=yPv;5`tSnZcD(YrjOj?e%CIjd zUWhSXvOzVgO^+38U8Qjj7(O;uI+>nioGR|?k=B^mZ1MG$KV>^1RYO55;CZtqYgmNO z82h^qgb}&BEZ{ZRX^_Z4unteCt0Kr%6dtm!)~wtij%&06GK)#&t|tej;iPN1N|Z2{ zg_y;Gu&}kY(LS(Nk&ly;GB=V=t73yzk{7M;d1;&dfld}?xCNisPv z&{$e?Tbbri`;L5dI}keMwd1>0s#ZZQx>(euW8%P}0g2S_w-wb=yk~T(gve;D_1WKE zZ4x?exd6faPqI=NK}zdW$IJwDu8ZG51_8CchZH$i`b7DQ120UfBR^=DzH(m+$Y?co znDSb$=w!ma1~-B&Gy9`YU3M2iIp6!lL$5Pv6+K-+w&aY|I0zS>-sOd((QBph%l&U3 zDcnOhJ`q`?M6AEs0I-R252HXUrBoO8vFe3coYNcru z7s=(4Ch*#DNqee4=wQ*~Qpi`XTIxmR6EM5U-G20j8M-xKZoJSXI9bi+|6?|UIqP(@ zD*>0vWuGlGkA#HRL1@2E9LyS5s8ilrpk_zLe$-}d609*?G&dZ|q=Z-NV1OPqIb- z$5yU*v|c5qkq z%E1G8qE(Tf66#$idF*v{1&?Ua zrT0C!Gx!__yt)*4+Vw`ZyOVHDrg}{DI0mGFLSPf`#R!*izJGFCx7Ja3P0eJcr6%W< zKZ` zwYXGiX{YCDI7Bl3DP-m@b5vwxKVHZBIN>Fqjp4D? zl=~Jn@D%arLH3B-n`B}zTtKHH@qX)47WnWJKIxVa%N)G2$$JjJXUMhsHpzV8=*XtN z1kvpGb{t-+R8I5MMzTB!7vdw8U_JES$7Y`>k1nFoY@h_h8ZO{4(ORUHwrt>DZM%)& zpDZyJRcHjWGF!^e+~w7`&S?i~#LkbG%Gh)`1WL?%GDR=uzXl?F>=@_c7&T@B8c|DG zhrYWAJ!N0XpLOA_&xymRx#k~br0$-}VuH(1fh4f%hLQ6^(X-~VdMZYkU6#}?vx>3z zLV_(?BjEdIP>1%qbhw4j7BH>5?TUdECbBUv*`B^&k%_J$ev-12)u>ORbf(24jR)OI z&bV%VKy!MS^t${>exOx;o%39xOJt6`fWzvS*U5zQ-G}8rWPA}9+p<0S@&roGrgI${ z@q8^LMHDu}@?P=xIUK?ZgyDM*e7P^;!%6Woh4x=PdY)*Tsx}jzv-vnbJC*W7qMMxE zllLznCGKtl7I2=$t{cV(H@&S4?k>ZYbMXBtv-KBDatVdJ1=nd@)@8mt3CFs4@KE7% zkcn^UcD7Vw;OTZ&{r*&agxmU2M-XPz;l>FHci48=mKQpmRIH5<@^X^xiVx6VxHJ07 z&(Cjl$mV3D7P>WFMOVi4x3zwvZ@N0PvD&if93B>yk_gmBv>S~O*|1BZ2}j+(Y?68SjTcL`|aE0 zhvn{T>gegl!;;N8^wFFIn$TGXF3n=g>YZWINsBmr~m!5*k z@bOQUZZe4C3Cc#h`8Xw3801V0C_gWYRz~$B+X7CVV<1aC4F)yoss(xZxhX2Td^h!O zr(US-Q*e7oKmOc9wW4qm4V*|la!H^xB?EtJ+KxIB_G-JsIUJf2-spxsjT0;Dmkw<& z%>l9I(-(GKOr;ilixVAnr=m#iwF>Oa{M)A#6TgbVo8mC_?h0s!t3U?P3YE~jU#GOR z<%F?%H&u16{L34h!eJzAiF&(6+*X^FHM>X^-@TpeP|1=MWu%bW`6&f)og>l)--1ak z*q7Jb<9H|JfyT7E1W;}R(%&1Jrq*vfI+_#hN+j6d-v=rbtMi(;EW3=eC8=_n7C%yZ z&%XkqujSk}A(_x?QAvQ`?_Mf+U+A_fHxh2C>F*!>Sfu6pph&GJkKh^*9%(Re+YFK+hL=BfrY58cy4D_G zsogO}%|Kg&?xGs|igmUq9pnm{DfZdTUFBJWne=z~oo4B;Tw@=}qZcawjstq+w~HVx zD(l#q2pcgdx&k<2$SNyF#5n)=(#;0rvb!P|h*1+YLFJF#mNc~wX#IR4wIKTU)5>1gHt@3V-y|(ftr}O14*LL#>${hcb&}%mXhNg&}(0k1L>~o&edb!s*L4$cJ`p}aByYzbFz`r%=kgcBU><7Q$(vFdxcR2#ffpf#8YdmO^E~!z zGvbSGc-Q&ZeWlt zHU#W-3v@{YDP<$b`*wEw9AMn@{n_17_XujtJGp%9VcT4pSw4_dEbe`}Os;$KWmv`) z&^0$9P5;&pZiRCMZ=S zll;Z5esO5%jDYiZ`3ARu@yc9Rf%j%U4M_mx3!5A+=I3S0Jt+w%p(sr*vg+#^ks*#7 z*)16kp6dkLrFnr=HGAH~>dR1^Z5NKw3kWDl1icZxL7HM6{=`}T6J=!n{I@o8(i6dw ziulYL$pMRucgU+{cL0aBZ1X-+)HgLfa>KdRqo5-E(q%jySN-)9S74pn1U5F;2By-UhI9HT5^BGBj&w&^B3hsA!v91zw`U{sP zhxJU=XV`1eHhT%p?y;xpp6qlZ-Y_{ReK|lw@EgiiW)`~}nMgQoMf0htlr=qciY@eJ zgRvoB)!#h&i93C!ciLY>WbQ61O~Z}UQq)QUK0eFhcT8vY?=ew!fb{6PAN}|?-8^SQ zcaRO{bG+AJKmLkMCsOK|+rq2GxEUfH(ZNBX(i_w0DbDGSPF2n*nh&pk!%zmkc-m%M zWaw>yYH%i{rNQJU@6V%EN>%h;uP7&tS-HlC^5BIin&)F?rrn%B_f(N@z*jDos2(?8 zFO+LUbNizSQKDnzCR&Ym-)FpM1OP`^8F{lb;C04*kORgvYgIsKx?C6tV*}S<`&0FMTQS9@a3*5WwpY;9IE61a;i2)~GLE z#-BcQ-&vwT)>Ux6w~|j1^Ej@Ae67h4(&F$vI9wfebuXCNm|EFb;Jrw(;>vsF?W2As z83K#17=4BverSl-V@uBRVJkPuP*iw<2*7^A*;uuEvbWxk9pg+|i9YD{QXFqylUeNH zDDiFbM7>?W0r++Bc3uz+K)kbhSV{Nq!=9Dth*DjS^NN&bcHfb*MzgglS zW&%H@S?XgG;qG-=>4*|*Io;_#KO3c|m)c$MrRRa^I`t5?_90Re1eH>+h2Rkwz(sOv z4~vJ34-M*^%yt)ZB_&~?k72{bEmKX${p}Iw4>Yt92?`OQVH~^K(v<`8^8$m#ME7OW z>B$kdE)tY5KU|O7j`KH|_!&I=iA-pl|FhaJIP^Oa?sZ(2RKeXr@e9o*sQVC@H1JvqU!;LZ_^{CEN1jfutE%+zT-4_f=mWpm{_KeZVklGV1-pk*>Lt7KqO zFPrmIDo=UVkp?O%Blpvz3QB%zxR+X}`UyH<>ccmDQZ`oq-4PJgAjm-pkKECqVXyq; zuoyv~#Ie#}#%;Byewgrpggu3^yPcBXt%Hppy4oLVHwtgCR_holJkcu7V@v|7+edAm zEOhSYKC&5vwr5Mp1UFmtoi}+xgX^x;*G}2yFUUkZe0GX3&g6@uXWsQ zyBThVb~M?Trb4^XsLp7c z8hH)H?weGD^6fFBrAUu3Z*wJ1cUGNVfqFiD&39T~Tc~S`ln(X>$3_Q6JD0j4h?g&4 z_RiEo$Fl-C1ie&0j*Tg$!2yiXKZVODg-(k#Asx6ZG@#krDuG%8$_fhA^G-hm_)A-M z(Cy~GlLa~M?H`Q1pK37ggn4nD6Ntl}J^_M_>hifxg1gI`8G614BI(>#A__E!+pm8) z4y~-SM=vczWqxIwFdMJJKB(GZBlG38=wu1~Z_2%vET+KW(0kXqzMrem;yCc>+v5q# zfiIkynZ*X5B9kUI+St9%CwLullj$FRa6R5ZM~8cdFL$Qdn-{OsS??Q5fZ(N5PZ@h=_z=rY~QNeMS5TM@(j2-;#HzB>le-bx`X9` znAOpX6WohS!w4Y$*+6RNdcwPV06@t6pWR?&${(m-(uHNn9D47p*~nQ|LbN}%{(kJK5o1zaIi!vSZ!Oo|1uqK)+? zEqd*W)>qiQy*f=Q)oqKOVCsnXF^~r=W zW+`|2!Tg(sLi^LLmOfN%pLLUJN2Erk*Y|C+_Ps$v3u~qls)yW&7ttPts*h@en(NKl zBV3p6h9Hlb>-YNqybIvC*)X^3hwupp0(|J)*9l~ z;`3ob?$v+%YahK{b*=- z#ul9*XUqKU1CLmzSXFTOGM$uJ(rBDy=^c^4vj(#JwhB^qUbh>aBwa`tZKl_Ms{6^g0C-@Uw1kxiHSbE0*Jz(^dF zGeB9}Z2NPovdpiE90r?jr^KekIQSp^e5C?VCG7Zo=u7Q$%Y|whAFQi}g4@h1(Xv0;2WHMFaWG z*9x*du-64~RpHe^Z39Op9f4)c`Qm^tEP9c0Oo6n}6yC=l9#!u!#`jU05i|$|Qk@bZ`07}c`Arj%lG7o0p}6DGHa@Az!|vF> zMfUQWA*oYRZsZAgUFAeu-);*ki>iSudZAHTTLDd*=2dI5btSQVaD$gYec+9m$6t<7pTz;;tl`OcMhzN(nu+IC$ zV|s7pIr4nXh~9Yv5Wkbz_6VyoV?-i{(dJuP8tBclCN5{6U*#Yl)LMxrbBSZ^j(RQIg(1J+5~C%@Rz!08PHu6@ftIbl&egB{(dd?2MhiE*}I1blY^y7 zMw}!+`1Wo^T1UX}dhvnf1oHa^KzvnbD1Hh?LuGdw=Ly9vLAXKb6`H-z}NfuA|Hd#j0to*HkB2 znAP?vZ)r>dvd%185mZZE#>d-vc+efQ2$R$9+h?pJcq6cB{go(bkd#kE(1 zdNPm||SJeu)Z~1ytI0!WwIVQ*=={u-DjcrM#g=Oob`QfWHTANYSWUs zsdl48us^tYes%o8FEbhR958!VWCTttl5peQeen*LLT-}FESHEZ zEd%Xa>%|@g;N=4=@ef=-eS%?!br=g;DJ#9z>Y{LM`@r{O%x5*87{GET{l0%Tf5U`* zbi7}nxuWakRZPLX>c5K^{vwC^o{I%WWVOsGKWW#m&B-Z_rV;m;>u4hfud3Rb%*0Ug z`DL3)=R&6&a-|w_OP_rEx8(+3rvdcoc1rtBif^OaN7QOJigde!oxn#b)pghR)R zX&9LQ?1`wPVe9Ta})0hMzk4ohW&@!99&8 z;K+N+*#E@KJE1T0Z2O(GNr^7!L#?8*YM~^y{96jg_0OL9^rYp-aU0Z*C?JG+Gr26g zzrJCVlDsCi6ZVM@QSaV-TX^9*-XMc+pL{~N)z^1%S}%b2L%SAS&MIGEeX>rhk(LJU0UJVHMmEmJJi0Nc!nm1bqRC>z&TZhQIlSqgf6 z`$V3`H_WDLy2;&VEhUG@)Vd>luvTgyUSbkB8^;(v60kNkUgx=)k-&xnyo6&mMqEFU zW&3da=n_^5lBgsG&NO?Sn84{_MO26MUD=zj_)PA;;y&vWn4ib%vLr(i9ziCuliRwJ zikjX-Llr}lD*AGr=SPtxSZh_j-&RjsXM4K7w!AjC zYgq-6l9F25nyg*#6Hfx_+)eG*^OQ_@?MC2=6wN)ctO@eHsK(KPH13D0hxHV}dPVUM zNQEiz38Qj4RHS3{ratgOtD1=Mh9i@X2lM%BZd6cf>1$Y=k#lIOk~^PxylrVwKI}Wb7e4J>XfUuh z^NfN!6{qUz)nx;=JNq9kFcn%0X;lwDr2Gyz7{q}J$azmC3gBfyw6RlHe?`dv2&Kvm zH8!_jIX&C&;RHQCJ)8gfI8s|BzL(3z;xL?4mfzMwv!!al@s*(Oq4Gq7`&PZH-W4p4 znWn;HHoG~9VbaQ$T%V6-w$byiZ=h2R`RylZQuy`(FVCFm!z!r=01n2z;dtdlv+Bu&ojJN- z*%}p=P>0!KT$NXI);|)_;IELz_EPq-^(aB95?w#X3<@OpmcXC&0+!4u!u7k#;e~x`}^mdb6xxF{riWD>tQjUXU%7fImZ}t z-1p6HGr~x9V`qe%*Wv}K`OvAusT;iZP_o>@X0))tuY7yFBuJxFG=Q$txHB`$#B#YE zYi)S&)W$PUW!O5XJ4+g-RFS{bS7xRdzd8CPf;tKFN4!cQ0jg9FRy)O(L8JBMklTIS zE#|U(Iq@BB=Vyp1PekAof{qxwjytkXb@F3$;sS1VzaDPwV!gvXksBep6EhDYwJ%YSwqN)OncK({y0>{r{+_hnaTXTr)4JXyW*_yX=qiUvLB9HLfj4d$F*Lt z5k%u@=5VB&`aRCWh^x1{M1SPXz>Jx!dg4RnSGz%jC2C}yrDaNr4*C?&_d;oTkbu$5 zv3(jjr^VTae7izoQ^K|PGlzEP1l_qqJZI3zm&Kj;=M!Rdx1G+ZZte}(ASnHWc8Eal z{4@w!G@gJU!jVCEDEQ5q)3*r@OIk^8aB})pD!Q!Lx5D=M-a#RyiBG^NR5u_{DZymv zQ*z&$B)l1#5%@s)okLpvEu@ZjYdu3zB2FqqzBN`@`MUsvlxwFI_{n)X> zlP|?X?l)R?yaVeMpHFJbu^Zy^)00tT-hQVl5T-WLR<5`b&-C-p0!_C7MrY+Jfe+*FMsu(k zd7C0>!}j+~cP|o~pFifVg0ZY^u~+^g#&f9vVWO!nMD*X}8hj~hfJ#~V&#?bHOhWqZ z`d1b=0Kb*{zbgT|(V(_mG;aZOJGc$#7(-wJOrZUp@6Rgi^6u{{?1mu$C*H5}$`;e* zDCV<(R|H^(Tt{nmersj+y^b)_ybjqN-|n@3^Y+iodx~!OPkqTY%alcn&+LsNu zHZi5ar!ZpyC)UqTZ2*MBxM$iDVA%u|cLXEWP7@*j>!B!rIOavh{~!9w|KBl#D%5Db zLh_9YDBy2_!>$HGLU+`TkVFYkw56D{Mw!tON}Vo{l_=uZp;ZtT!IJogG^?{6u%ABS z($#JQwf|x?6e+y=GV|I&eSV(2|Q63pT-;a*D z3`hhUQA_xT4|SpEUf8NQ`ll5!HJZN(p28w#5Zu)2iXSGlu5WVNfvpG zwsC${wW@5ux_uB7cL#uBG_SiH9V%(F7L09;{?ie?jV_*+jC3~Zetzy>?3HA+O}r*# zuH%HPC`k+-?&iy#6YRmqZw8Y6az=4)LKcpiyAEi-?tnDrr;6ZeZ{0@V&vPx*@W`e` z%TY`cey^R8f;#omt68$i`E6}_x3`egZcpdAStS46q*MXK*7|U(3!L$~o*hXt)rBs8 z|4h8Q30YZ?Q1y+kv7Y8j_QZ!2u(!Njw3?pKFlk@vo=Hg|B;sfw!`AN(Nwj`qCI>pR z4VS5(ntp8yvUG+^y0}W-3oQc>nedUl)XHBw8JJD(I>g3nG>jz6KE3bmo1Q#+0(pIX zXvFNS#GG3r@X2#J=SqTVAwg!et8Kb;+}y|ejq!<(Aq`{&PN0J(mR{wPu4<`kE*T{D zFvN+FZLNNFaGt3}9yPoW)RZGO%F~vAZJ4Vl9M&@l^(NAZ+l!xfH>}j2DrWT*vzV&D z$BM1a&tAU4peCVNkGH|m8KWUAba}DZQ79ePrBN>VF+~P$f$<(7bda+e@z3uVAoLR| zqjq&_ERAn_u{={ivlwR?G@TgkrCKF&Ggyu&MYd$g zs0VbP!YkK!-7|AknKT3N&k@^FFeObb_yI9X=24Rm`T3SmdoXEvS&2fWbp)s)#alY9 z)68acez#x7x0*=*w9TOTKBw53jEh;dGinXe`SF!AIk!=QHUS_`Q*3^{C;<-?NcnFMey?vjSbm zmZMblZi_wP8SXnv?jdBJ=ZHG^1|TLdMsSq?BY-gMhnpRePGs;Awi z*UWq#CtGW~*pa(c(rEcE<0wz$B z91Ek$IXQVR9zhq`+?mVkX4V)He2eJt=-5JJagCH`B#1DAUMfo47t{RS_s(kj`uh6h z0?pACEPiazCxXIq&?vh5Yx}$XPEl_p-loEJr#l&fke=n6nOOwjl{(QNf_OHJ=kY3z z$H9bm!YNxaiw%RKg{Wmnn9T>4>fM8u&YrryTz-v?_Hv=9g3ku7(JDB*2cHDs=}27~ z)1GC~z%j2mfo^8w{8rpXTKu)q+{ozYXoJ#(SQdI2;<3U+o!l{)t|wk7_nu9%SFX4O zljcx%%H&MonzI$esM6X~qg>(ZdAU{IQ86XxgotCe>iF>NNTae)F8v)2ce*+onqFft ziF%eG8YrwZdbI*Kj%R}gq@wj*Ma`bwo@}8lO+FSh<03#9U471$>if&4z3nfHJoNvk zY)(#5;+QP--WxJAcH5J~5YwKagkkRrtF+X#pmtWv(}?BXtXdYSOu7*dssi)MNa%@& zqn`Xdf0Nb|XCf|#wf91LnIeH2l;bYmq9?u4pf})+45|CqMgB!`%DE_HZ11YRg8M5r z3%zuCT4MM#EhNfw%cr_W?jWZA{9C|{P_NlaSr!uuA!46hw`~ba!)NA$GU{dGTrz0{ z-Ey>r?u)BgAaVLk|lBQfa!KTX3+G;5ESKun{)C>p{ZQ=#n-PBG^ zAN{ZN1(4bpg9G;zJNxB0pI9BbifXs{w<9zb4;gev@`*uZRsXFWEP8~s!V^{?tLrsx zHu1%QGboB`=@z={K~J{^cRH^i$&Hl^6#i+6{TU3Vh4#4Nr@0IqI?0cpX>wW!VOrf_ zHU#OYcFkQF`T;plh4sNkGnaj??FpP7C%(~I`&CC|kjZcyG(@)escT^Ll6@bmPv&r- z|EC+X<8s1TBkbXEmsrV(_4fTyQ6xmX;oA`%k*UeQ%^^)7@>?rRIiJ(D{~kOoTkI(m zbj=|;ea~jk&2#h-ZhK0{!|YbL>gKOLaW$T@du?dJnV`H}L`t~}W1)-X8;m?|OI-w| zrc9G1BE&Xkjkig)sy*Eo3N%G&;fm+;9g)LQktL$W+`GGmA*)&J;zP31Rir%b71oVj zH+mm3X{kXW5QbdV+}UzZ_#Cvo5)C%$>~WwiqDv&c^nqe{*d#E%xq0XbZ+5}x9ofT- z=Q;c3soTDboylM&>PGB4T1^abqVXep$Ux1eHBU4dS?EB%9G|H&8H#i4EPc`M$ZWGf|6~V z*3wP?aYW2rsqexg$=~O}Bt*=ayN3pB@ z^vQnDLOX-+&HgD3v+)uQooteFLRkcNZcc?*=X=-H2w8B>VvZHkbBox*D!spWnTYl7 zQ@d2|{qx@{1Wc4EzJMpNUJ@JS^*suaIEvJFO7iCvAD+?_fAIF#OY!#?S42&Jhk_G& zkAgxvcfft~fzQIxTeeQu>V@!m#%dr#FijsDpBS6yYJ++Bq_lL0*?3?@5O5S9Vezf7 zzf2ESp;0i>IzMYWNs*7)yndhSvXt=9xz48<$8HDT*D{%qe7{9UbB?YTon$W5^yN?Eb+I`mw zQv{Od`;45&Stj20u5-?+HKT~LD7V{JwU@h_&*5K^84N|G2h|Azay+}&PaRkKd#x(LAN)-yzMe3M4s)_M zlrd2Ub5iy4v{;s^mZZYf%UA?+WGq;X0uESzMxo)2fGV#2oQOs6*AhV?aXk>Sh&Qbf zb-zZE8r!xSlq)(V%ztmK0!@TIhck3bU0m6(yt8f;z3*3q-aP#ap$^3cWKwZb-2%U? z8+pejMX(q>-RtQ4T}we){uU9~x}nuWH~%_QeyZ%<&HwYW?{KOB*Z0R)*Faqz@Dau^ zXjWvu@B$>93OH4+@QLd?|F)ZgWsbs%ZlFHV=a{ zaGJIV2&ikEH$k*A;*UqK0@dLKq_f>|Y&m6BcN|IY!^iiezM@de71kCc zKV4hd5x4io9}l4foq6cK|FJtRG5DCGmy|=sv2q+i;Y_bRQ8WI~e87Q8*UL|le4)ED zdedq0nrrvT(OMQ_B4l*&!(;F*v_aS(ei0tucfH&yMI{y-`0ibwI4d=~>-It$_%ddF zO?TDW!yh2&;H&MI_W@(2Ct^QKCQ+lztUrOvUZdQi9MGHN(ke{VI?Fol@p22hxVQj@ z*K47{im=cy3-j05)kpoGav z8$fmcn1;rz`8B$z3}DHYN#HC7mID}TlnS-D_Ir%FV(h+zQkoD-d(f`Mvs-C+Twy6i z!?{kOr%LfAc~()Le8CDip8Dr(td}eBNf-fRJ`OG`#o8;9p^VPzJJe1E+KAp@(pFN> z&_Uy_vGKK6`F_x6LB!|G7h~1(QX}!sTQs0X<2JPT0pKFH1OzZh9d%=uYRQavx4-z3 zdu5}u#y^LlJjr0gjs|F!G_jCe?0wybVQTB^%MfI%~|^#`o6~EJrghjw8s87(x;_U5b|a&PG3c%sb%!Qp;hj zlnR)Dt?U!Ur<2+;&}ZZNHkV4%DmF?$hPP zmUS-o1i2iqVjk^SE*e2|l_90a6q8o`nT6rVYUd|aKz4fQFAox99B~SZCrmX1BdHb4r6Cgs#l49^klk-k55SpblBvn5owsw5wTse&Ecz)5QYh5aO2>aiswP z5`3vUK2CX1qSAUAgwYc?44);7 zA9@}Suvx4ueiCph&?InLmKg!_K~?K)$t_cvu=;B1FxIrQ@Mk|E&1%)Vw=?B&SM0}ii{a?9viTYV8@8^;w}$L816ZU-u@ zGsAhwJWlyuzL=NQOY&nmn5sMx@>0<%mQ$RW`@{d-xsq}N=?dDQI#PoU8ad}^QNW70 zGF4q_%`g}Zg+en6SQ7!C{j9h5C135K*OQ>NG0mU`UD{q(124y6vcf9JANa}UL^cAy^t=-|zdrO-)jniN?ABb)7z4kmV{jS1;$z9k1I13BNdM>ZWzIt|T+#1o2*nYwd>iv(w zx`KL90=;c>SwvE^;zhp-Ibbaxtc$?EV?9v@Vj#YL{@yZ2ul4Rkeuxf>o(UlY0ufQ1 zIB)sVe}8PO*bpz$JW~pG6YmU}2+_UIRVj#j*xglQA{eXj@vws)dY7vvNcwV&ipa)9 zxs)&9p5L0X?~EpKTh=pM0H>j`uoT zi0B=KjsiaVklnST9jXGpFSIA8_<03R&!Sx808i!nQWI3**yt5;6^pOTG8!|ZJ2XXo=$blD^z+G5F^>M$ywera z`^e_UcL9K7N9#SZcg~OE192B1;V+yMyQ6YU#O;s`(ytd|kI_tQ8jdob5aUZ#0!@j7 zonC%oG+b{y8aV-CuDC@utW2Jc-F?7hKOt2h9(Heu@&VXxGtJ}_t>Q9EdqyQi*z#;U zyO6pX199|&56`&Y>`}6%3Ly?QLoz&(Dhu~jeTw?}G)JNIhyAZ3bwX~E=3a}FCS`vy zL!Ima`X_`od*8M)@4qhZSgA)LKy6s1%_Q-7X(8?{oo!y@vMDz3 zznTUKEmwHr-r#Ygvdd|E=A0s#&*QKwjEZa5^vzxh@Mc5A!RLX7@e6vHIekx3v1;qUuVG|b2I&e)@>L7vb+kL!x1tmt~ z`g_ktcuhP%2TI(zZA*bkZp05c|0hF=82VJiUro$-yWdLht-@RIoO$P`6qdwTZ>;+H zzvLQgZl7IK52;tVq#Vg}X3AqGk$=GR4ok6cnEBk5>y25TgD9?g0o z3QXD^c+_K=jms9(mc|2xCOYLc`Etjr%4{k`QG6Dt<#x}mxwb?2zxW4O&sL=fbSlp) zU&^dzgMY|o^A(ME^Dd8)CNe!gcqHFTNUxGJuvltZUO4a+v2D}1x3@#DRPo~D@38?T z;80YE1-lG9zB>$=7$x9<0}}rrNwCy;`2gVsi#x$UFa-oRg4n?o%0t#9K0ZEfE@gY& zhFG)M41q&~dBp55vTq6QUV@1R5t*NhTCM7r<#*q8OpbTj>!TXFdh_mwN?G2$p-+By z2$*#8Z{5Xf1|c6khy!cBKaY4h5id+S!Yl=+NVV;8d8oM#=l3`_zYNGxX|w@n!9!`4 zu9)v`0r>v5PKBBWJ7wnQwdc>Q4IFpITCh?k<85@FI$8*{yoKR2YH^wNG>HZQO0iMk zqwI!LmByXT5)r%C%lEHbHQQ-(PI9yO`pK`6Nrz-A<&|JnRK1&VN0K&2(owp2O2K|~ zZ%m4`*xT823g@cx=M`gvUmX+!OktV@l_UU?w!y8)9kn0i)s|N& z3Ox)4T1jf>lJuub>*Ju4y?rQ$7_2g`fbjgP-$eYAeR;L~Gl6&Y>A~!q{qxppF&mo1 zPUo)@cp+!b_>Z#h?me>}sYi?g`a}?$X1eY;%*c-96P}*zkRQPFcs`e5i~FkT!tKsq z<<|>|GOBOeCG%}gpHo=Y8=u?FI~am@Lp&d(YD0?Y3#Mi64GO-!pUnEJQJr2&O6=lj zzxnr_7ZlrxsYbZPySa@4ofV*-l${kyJJe4uW=#~v zj?&LgS)<>jk5GkLK&y5pp51pdeGiqE#GMvtEPb#6=UMme#1KBC++5Rb76>>i!*VLj zi<;BRf^j>y8L7kc?<$X$H{yVybA)^gb?RamWXY_Guun_pbEQ562>?)r^*ds>^Vns)cPBBzsGl>^)!PivgNrIB)78C&wNQWLg;J&O zzYAXWysy2Tm2t-EvXwljv+^Yrz&9kWn^__N-@c#Y0~FQ5sr~Qh!K(nV_Hig@mXvdgz`QHDQLL5y z1t)$$mo6kxIaa^LD@f-dpQ;jnb@ff)VDzI{Hptmc z^^)`v%>rk|;xSdO*S=y=)y};=_sVxyPXln<^9Nh`ifWzrv<|k$I;S?D8->|4PWPvZ zpu?JHA?KrjrgW2_Xz&^=JY5>(o`0MbfU_k(Dv(?7xY&};PvxnQGNY9GT(OL;9|twp zSg#o2G*J;u5|>qdjiQ`9o}2iLQ_g#9aBpv=rIgh{XBvJ02YU3p`L-S{RU`VZiWP`@ zU1|h^h!op`PkG&#_z^D*-`u!UW?iIH4>jo;!>;$14psq08D=z{uI_TLz{xVz+tBYkJ{bUl&G&@tXH?#*!0Xd5B!3IBwFh4SCcMRvps@~DPa#eVy z&EzyAJKt`870~pM@Koe9HYN@`Ep`|~+OOrKDn>mCZhapn z;FHlh4JXMn^#sIO8prb(3oiOiqXCyJ8Mbd}WfZDmBy!!sSxoY8h6o<`Kn9zuMs|KK)QT-6f zq-zwrI#|i^LXA_kaMvW(?+(Z2jHmT@N#V0+VX{$>jcUo^Txl}?vk?6jGQ>{rpg)xF zXu)o=aZ7M9SD6}??jN?k1Ux`sN3Uj7=2RknL|0iRxuGyr8C`l%I<_Rk5f;9)x!ka^Y5Xqbpg~L&JM8O2)0Ya*26O{uII6z_L7<~;F74?~dYw8~7PDgq z%BNiqY(GO^N9z*Qwv6&qz?VLUA3=0Io}`L}sNJxoak_jt*Za~K5`(3##JD{LwQ`$TG!ZQm9?5(yR~p4krL}_b;X2nVtj`Y4 z5J4U9+xJ_r+><<=ye2C$aGewRc)w)dRc!bt8<*AtR~kOyXfoe+XDz*0q8-{uHb62L zz@)-)CLKu^IlI%VI^dA15rCHKw)d3()Zv3nA`{;1)vNd?t65nEwTVsUAnUlg?9l#9 zZ+Sei6N^z6lS=>Qb(f;1z(gMOu7n0YN?$A+UdN8rHKko!A6c(MpQd&F!mvx^nQk61 z(8uo89)6|XO*zO$#CNgWHLZi@UI}fE#Qko&aig|fcGDh*CCUPR){r1mhXl0+QwcWGN1H^9k?;8?h|ERRuk_BaAVb+ySo9pjn9)#~9D+ z9-Yc;mhp%9`wYZ^&^Tt(#;$ z@}dns>D+ku&9A9R@J4-&vu=^zN1bxOk3{4-y7Zvc|1?j3swJ~a?E`BuyVHwOEIzY3 z^Fj3PIdezj$qM^mQiSgQI@UMk^3cb+03JHur5+yX4Y_e{-212$RZ~z2?GI90dsV^lVmLRwKXz0{v#`meGb)L3RTEGL zvY0&QHCK?DcF#o5NaR7JOU#oic51vE%j(5}^QBq|I&{WL7fVLIG!K>vi)m&ct?}f^ zx1NUPs&r37b<0NzOf8=oBKD0nDj74P*-eIm!!$C@ICL*Bf1g*qb}M&pcMxw##>J(| zT7;!1Ly;zB@x9|3uH3hcX?MVDIL(QR@t)o0krK_Is%|;Z?`qV^QOt6I6%1?mOX!*O zeg8|)ljOQmPI#?+TJwaj9E&($lpMUJ3M6mJN7rJ$4sJG*6LY-`a-`2SIAv!v=M6gU z=75131(dtrmz>=%2QXRCmVbZy?Vhx3jw*Yrj#qVCR8M8j4vmj%XgCQsf6`b*-6u@1SZTMfB!5K7YwvJk0j|=a#f*#F`S{Csd3r^ zuE^}>&_`_Z+U!|cPu|w^_(S@_LCe!)G7JJf$YkuIotXWB?sH4jA-755v8$ zF&aC#-O{;-?e@)Fy<^2sb+OU&r8TXgu=p29{8#NdG!XN)>(Qohtrr!!yM0mzbVIwo z)v>FwexM3JT}KE=h-=(yQiKlPu3ol`vl{#+u_O2Vh{O7|MIP3)p2<{uX4yV=|JdH8 zvVn|JT3sx^k+QF~n}sUZ0n<}c0@wL;75_sTUQ5JK4s3N0VHt3KNMzwyEQRj{lLhUq zT~e~Y1vwt5Ru3Bv;s5z7LN z?m`uYgRWRvx`u&QS)T)s>P3T|j&!%7X3&;=ihICvEf3Wvw*0F3A5qe6aW@qIk%uxb z`k}Mo9!Gp5o(B5*UxD)8Qjmn%eN+>P6@z}|KR;i@)K{R{N}c>DLt3s-yEd&JA1?;* zmw3sCbUk>y^QBWT>)#Lz9DgLCOpq||FBi0y)}u0<=@Cbv@-k5W4Z*zq4rJK@;d9g= zkpdy`&mW=U;DFl?wb%U5Gn`94G@x8YgAR^get!@dHQxvPAmUpI_@I3BJO2C6ut+ce z&)ohmHVNJw=)$1lptpNCtW2&O-tfACzJSCAMKAxS-2=WB+NXIuyGTg}+eUALqP-w) zZME``oWqd}JbT==tmz~E`B0kDTVUXJRgFD#I=JnSuZAT1KFBe`56B9RZP%KNOH;UE||-I*9F^3FhK1a^9!Pti=7bp!xq^9f9YMz z&)4u{eeteEHn1=}NBn*D3dq~936T71qy91Y6ayH*`iJ_*zjq@6D$QJ%zJcS^-!BW< zcM1k@#u()L`>FuwnZA76_pb#H%ok`$(u~>v`|33?Gnn3-Kr8N#ajTF-;s2T1|8=Hz zi}P|oWAZd#>n|_5cwOEYz^Js|NhpFQdcZN?5m`3b|JzqC%+xjoSSZF5^BcgQ-wJGC zGORnXW_r}VY5$$tYtaB>6MP;g2*LwOIR`!Hqdm)sU1hG0%Jv0@Up5i?80qpL-UlxK z3iVM#L%B*9Biq{EP34ZGOsTX@WFIlvkW|etS@N0tq0RAEJJo=x`9RQcU*Qo?sWJ)w zwq;qQ81S7!6wiNM3H$~{3U{q__RjrjpiOsx<30UK*LUqt$J??%_F6QY-2By;d@=OX zXTWOzGwlBXlOS&9^A1R;1d=rZiFv7k=sxF+$cVngIgej!n814h|7=u#q$Sy4%iXMK zkk7)%W50W)p~N^#$29uwkj9hAZ!j3cjlf^T?oTB^yR~c$(Jp9h#}S^}40#wUAL}Z( zNHgmp^*e?Z7Y9M(>!Bqru<~M~P&aD6s3d=~ILYw*Uy@EiV3`C41E87m{w<$8o`VUv z+4CbOjEEnizQAp(Ijq z$sdFL`s&~ooK(Q41Bo1eJKV)c1V9k5`gTO--&ak6e%n$5$|1KbZ?u`l9;$NRXSo`tcb267ZsY2BLc{S~N6>6p#_(P}SJ|39N^p_bc z$Z&m51m&x+v5rGIAszBb1kyo6{Soh9>jNqd5=;@sbSdkP3Ojg!>s^O`P{1Jn<$v-) z9OE6VfCn*&sfW{2S5Z!gs9yzqx&3=KLT-x#(wO`Ar>Ne_Q2)MqF>}435}szNb1spIjTko(VRc6kft^FPB1+~{4o zT7U7X#owYt&CMBc(!G5R_O?eMYT&HvMF_B1iWIa*j69T}fA2y_C*0q=b(ZNK>mxUt zNOIl?k}NdAd-oCwr9@EcgemSPg!n~kS-kc0HU#}k-0Z0!a=p*uQid<=|~AX4eblKjcfk4;(|inbRI0^h{A) z4uIMe;FU@Rx$z1`zHC?>SgA!yWnSA0FZ^i{AaGZ^_sz+^qSXK${p*>M&GE2aK03|q zyLU%r4N#o?6$tALRdAI5uYV*l0!La^eRuX-z6QAhlps(2f54#r z{jhfy5}taDmkRm!-!Bk^0P1u4z{LB{t8=Ts>5{zOtdRe4uj}{S!Kz~f@gt=8^Qub? zaK-;aAJ?1of80zBvq;o`&85IU*VXRbyN9zNd|^#nxR+b?V8o6!MHa6deM^R*>Xxl9 z0-#XG%!70We5vaYQkUL6lk|)KCVO~cv`hMr154~GPT#&c@$~lpF<9`zi|FOK= zic-8`iTtsxhIXNX9J{#FF?`g+tJNHkZN0Y10>Um;2%;?GpL??{ z4bWNg6~_JjMK1nriXIrWj;_Yv`xFV-f4T0b{%g$0-{z3=)d$A|e{BpDbI2Hh5*zK0 z=LB~+KyKip(IbC*nlCbe^P~B9vqAn=r3wb9Zzu!M_Fu0N{Kko#B5~ormJflZdN9Do zUIvit{^MITArl9odpG`GRW|Uz08plaKX<%KD3~A%A;FPH&ey*q*h0Yo?w;m<6~S-Y zBD0OqcYi(L1W0 zr0xIDJ_{@_Ec%VipPLNWiNSU>YxFHG4EO<(qOW~tYu!gPB^Rn){Nrxj06`O2 z6ziUYwYZa!vjs`5OM;%hwc~C9TKg;g4gUweol1)GHlv$8WIN882a0G zn=?NB^Qx+z9umhm$Ax7t!#8YkN|q7qHe`K8U*|7h)(GPS!mLGoa`Wpj0){o9sWh*Y zqhZu_XffY*zCM<6a^?tQL@W_Ma4=gVw)vEi3?z)XER>=RT8WMj98$?%auE-+Fi90! z1F~fE!lZ#-(){T`IoZoIaL~qXlk{@`#RThPnrv`r4jSl>j|(aTe@GaEc6qa8Cf&Sz zb>B)Gh*2-u{JIk&N9f5SarxnoE$5GV=bRmi|3|PMl$m}(s8+1kIiF@CE7b-pzR?y3 zZ9z;Ug`P`5iT3mu?~&pX;)&tR#*jpL@WwPkbh3h@PzQc8VfjqEc0;RnzkI2?rKM#D zk12`I-UP1?1U zxXZ1ys`ciEHWx&P3wjmp=*N}@m@tgFqrx7c}Ag0};1ZCFP1YFhfB zLmT2~#e&;4E7EUWmuoP|#>D`9i+gjyq+gvk8@6WLL3flcP(d}fsn0+RUIiM_c3X34 z?)x|6pR`ncel8|^wi5#STH|k3#uc8xeaTTuj0j6#8m}RYS>*wHcIj3{Xz15jPtyeB z{)P4qC=lkd)b-2|-XY_yiKNRYk9O23*8uVdVbitzY8Ckwa-o=Po*UIO!?_H1`S~Dz zI8KOa_m-=*N3Q<(Y_ifniyM{5;36`*4aE6(&@PJlmG5QsOjO&x+^qLRK!FA{%DdvDG%LuyV(YfC)sM*tr$#ZH#%wVoVv$(d$(!VYAlmaHbOeL7e#wO z@BCq=cnV?)6F!lFUQ-V_(I>4~T^Cg{QGwLCJ0q2kz4O(f+I88LkV36kM#YES@uv+& zes-*&iEqs`qS}6s-Ho3O&6Hy{yVLnch=BtN+>b6_C?C5-H4P`a!<{ZNyZXmFyI)%- z6u%#c1nicOH9Rc8@t$t4EnmGRU>)|gWlu7m^3@2p6J(i`fw_#)Je|d)bAQ`3S$!FL z`dy6Wv7%+1k)jcv({ivNXFx~@*Kj6XYo1bZVYb6k0#`T5jsrCoS)JGFKp#Fsmyjfl zQb11flg0R38kIsnnGc-7wpJ|^$qptl4eg#FRhC#Pr1d>{eY*1!kVNjBsh_MrDJl1E zeq3+WmlL5AX0J=H(uG)vAl$5v20cmAiR#e~F(X#yuj1JTho(L-HDuqt3z{#J01ykR zUDTAHtsHDJA+F|YwbVntw$^PqD$1m7p{@2LX{K$cH)gv)lOpJ1fAmIxm3PWisuS2O zpqCSmeqz`o_+}q`$p)MUfwtn7L}E`*cR{nPm&?IMa;8jTk$D8r$H)_`cbo2vVq-T6 zB=BL^dkQ&m`TXovnV~Nooea;`a`Fg+ny>!I5&Nn^B%OJWbXW{`nvnl)8NZQVu5!8Y zyJ@c;BHjt>2I);sdu|&Ijy0nPtcnX%j@Q_=CGQ} zVY&aV^`*!8StYlF8NZ&llh_Fm>1Nvw9|qk!WU2+5vkeD2t!{fA!#QaVk90K_vop)= zJr}Ru+9g>7tM^H%RXj8~8Au`nEw%+DRks_Hw6lhXKI&Xt7A&Cy|@>G0VuEiK=WgDzSLpeKKB+gWOx@ zBhMeuvzhe)5y4(v*Tqs*9rUv^_jnBxX#P&ne(6%rsh#+jYrXvZB|w^yK_NvD^acB? z6Ehz&f%p_3r!arU6#PK*_2IVIKJH=d?Hwp_6F(J=13Etni z32FlJG!7+*?#}?g+nXLl09rW`ntxxt1B^xHgZy9ABDZZbK;TEuX8yODu&p52Qqfs+ z|ISVdk?BpwL#sa{yh|uDz$dwUMDc#C96vLZrbuwJ!lCs4BGrrzQV#0A>|e(iKc25j z0o*Jyt_;by`tJ=nDM37mN~HWp$^$lgRpctF5K-~>Rchdk2?A+I$kRoD`6J4d1UFN) z82DSNdG0m%zIV)&{!5LO7Tioydg3o^>i=|d6+RU|2@s*w5+=b=yb0P@Y4!ZxT@NwE z^S?;j?z{R3kYk+JNp7o#U3RJVUJMJh9Tk?ayVZpo`Q~-i(t8~*_+37fel(OT4E-$a zKgg`lP_RRUg;A-`^_c}x!=c`-IP19|i{JMvhnM|bkmf`_>3x#nzb8Ny>0*-MKR9)N z|A`uyLBi`aqQ9qw4mm9n1OKHUoi31yX0qIyJXP=Bk|G3|ZtxszZ&1ATGi(Aw`k-Q0 zx$W)8v4Plis!HmJ|6FUTdgu8+fo~&RQU#_eJ1gOymDU*{WYd-rnnil6(1r=)gHTBz zws<^{VYxBe=r~nH08pIM+40QAaU%tYy>%{yUOS6nI?Eb|Sd(5pqv>@J`vHnX`7*QC z@AHsK^KpY>qxSGxx4nnFZgtVLicT<%^k4SxbDvtSX4e$x1#{FSJ`BC^sh&8*y@yz=&KeDZN?qf6t zewR_==HuxK_=_OtgAD@Gs6d^$j>ySa=AghNn}vL}@6SO?xgj?ZuP%1~*(pJiM~TC( zkZ6ylO#vo47pte+GxFdoUpr4Th;&f(GZ!fTJB#Ru&1D5bqtI*l*e1-d&_Tm?do;p_BnL z6TImsFUGgE8$7JH<}#f(-|lUm1IpRO1NdZ}L2DqFJ)d|a9lW#`6RKW%1a0h@s?;CtjpEk{M&GVi`Lvi#cV2L^_q7S z>U*{~I!^92#%tPB2r!&{h!+p2Mc?z)H>UEmy2uO#={$I}o&=D7y+m)`iZ1a0#IH!A z)GH#;gKswjdXJ@(>N4!+?*YXy<{BV~JL0ludb|rK_bB3f>QQwz%kS1Y{}~!ce*XDA zErX+vL)-Bl1_0P9waO&bRRBI&=b0m`wITk|0+{uu47wBp_MoZyytpt|Hp?ZT1ti+m zkA|^tJ!X3X`uYG$7s!?<9@90DG8?t#tHT3PJPznCFJEDKk|7mcY`;wDRBylyq15GWNJw7U6Mfp$N@LhOKM;^RY#7gM0kGt2#0ab@odRa8?GW}Dv&jg5Z8 z*O~oJ>xb}ftt_!D%SAvY`?u+(-}?YbvpjBHhZky_#<3plN2+>RkL0TbldN`~a6Tkr zqkB2mBxUy~q0Im2=m?YSglQ;O**CE1#axrd#@#o9OlaWsMzJli;AyGrrb$GwA8gbg zW<*CZYK@J59q)|lPKlOZ{}R@Dqw9D#$3iBI*2^7Uj+Z8O4FJPF>R%`nqkD#o14+6E zcgehZ9RNNJa(*_StAq|P>(=EK(gT^@MJC-IJ1dDim0)r;3bhh}1;xd(`;{0|Q4em; z+$wKhM%KOcRGYrpoI`@a0ommBi{_E$>nr5nQ!f4uDm-a~-Hu&#I0 zjg8en;dn6y1#r6WJMNlNtH=A=9x#=d4ycxEkz}OAQlbIhli)s@L(QBZa_OZ(rGXvF&zBz!MZ}c;SvfJ?W7kw@B_CAn|I&qk5 z(iIfiB*G(Ln4k_-%9&}8`R-W`^wP{1M+*>(K+sfG(09hgFr%9mNT}{DMnm@3)kRW1 zbW_e-L3Na2Bi)T={bz=s3&$94A9RuN(jktIJ@$r^?Vy6~MpU7FKI(67>^;Iy?&U+w zF0?}}N$2a`!>~2-R6MWVjG2SQH_!4LCvq2rkc@louJFA&4B?Lgt7zJ@S29ohX6sz7 z5c|ViFLAq)rqSrL47o9mKv_NEqNji-;df7g_+y`u0;=;NZri!k1}xH=RLFTo^~((R z#mKm5#_6>Q$C<9!u*;Jx{V>r$wKU>^e_p{<3ll7xUw6m3$e%5CR#sZ`W+;bA($iUv zzs%f7R|u4^c(K2ntXpN&e%XpMMJVn%P)J=4U^-Ju6P+p4?j+}S$N??T0J)ha^!?O7 zgBDFh_URMY*4Ivdqc~RD?XSKtKqzIC=7}Z)>`IwjqvFxo?%-lH142wc5_=g4v&q;v zW=#c?nhwFMb^#`RzT6Vxy1NqTb($MZ8{yd%Gt1)`m*)@GY0F8cp5Z)aT$mGFLmxho z)*at_6AOz;=V`#hPf7w96!r_^miGQYujk45?!fUt3fiH?(w~yiHE-{Rb^EP(2agA%KvvbnmNIsu@ztjdq41 z30#A)KA>tf^h3z_ffP6YnTy>bF5UapZVsU#!2*q=ZWKG&Pebn~l&*Q5*ZUUBK&>Vf zKm#dzTq394&grFmOF230#is{a85YA2VHJ$?PWeEgkVb1LTQM_muu)sr(=qm29)qUa zRn&9^OPl&~NkfnaU@lWR4R}Nwb?VZtX ze5#-n+n5SV_r=s6Iq*H9lN0Ft9K0r4zQXJJB`Rm*D~jFmVzBv5^8r*=>#5=6?BvQk^7V((N&TM2nictS&&xd#Hn5S?Y*qL~0lHBK}N+QClv~c0^RX|HDRm2@yI^{ z^Qdvp;`ls$_pj&Z@b=2`llC=0ZcL(F!2p&$$j%EmM1rkN*M{@_fu?b`NksmYQt*-h zU>kEd=gv`Yg;cclBrDG6N~idN6M&P?O7^Tsbv+omBm17Uas{c;T0uXw(v`Bnsh63Qmw1y6QtY_s;jUz@GBK4(0`c|H1WdXa!Q|FDtuPwDu-A1F* z;3v)-%`7G-JU|3J6zq^dl(_H?HKyCaG@8>7ePcZ;z3+Pkd+f?bEOk?5H3kAXFDTtF1>~@AAGI0$GtU@~zfkef#t#M zzFn1VTCpGVVi{rX%Yn?5)~CK-^6&Ddpeq<#+_ISRC8@`L8J^lCgk~ah^KfrelZ30p z^z7uCJ?v;F+GV4<(ihXpZmua=G<)R3GoTlCYyh7?1H$!^Va>XEB!=8!P^gVu-ypF3 znVEXXC#AO@$dtVXG>sa(LagDP-bUtn-dX5fad_3o8V8)y)pxiU()RrQYx8+>+B1}L zPTGR4_CH<=;;`aQ$)RLG8R}O09DLgQ2w+PVb~|HPIJy!PvkFD9io4RB?r?`~2MP4o zc$>JCjWJ6_jhVOvx>o`StFiX?<~Q+enyoJZPK{A}qV+hNaJ6-StesHn(!Gnc7R ztL0ek?aeTKoh+Hf-HFEYI-rHT5D~OlUn#1n&s4WH_e^@^mlpC;mm|=E~45UfvgHC-rfOEHLXyC&`q!q$m?U{qd(piG3#_xj;V} z(UbV4n#$9BHY|u(_U(kxne=-WSfx!EB$VdY515z)*uob6|m=C%0K+=d! zgU5Lz^M@QVS$&1DpKST5;rDOqi2Z`I7A(?XjotX~FJ$zE-Nb^&X6@wVV=JPEUW!@e zgwrZ6VBX7+G#>UCt#hp{m^}Lax!z4PMGzDAyw*H1+xF{oJFQCdN;Kw(Z0}l=F3{W0 zYQH2-jBB;tUttA-!&AxwtS0Kzauhx!>vm|@j+l13x-(N*hG$1x?fE+R@d+J`) zn!tS9AmRX8INtcRMX2lA6H6!9pe)B)-=xhox~6z8`z-c|p(}}`73P)R$0K>8-vHtW z#>gy#T#hrTXqj^}$)tQu*gDY2`#&J8|K&l}ZXjuPW+`VO3lv~?3zC}<$1qA_- zl5UU|Nd-X~>7fRJp}QLq0V(MiQo2F92UNNnY3T+Ta>#d~dwcKuIo|*C?f>Qdz#Io0 z!!>KJb**!)^E`jy!TZY%+4TTxI9I8u7V>(d&{1a~CR+TW)a9iZLz6k0Vaa?Nh+C~ROQ^N^~*C=)mIB9?D`MUe* z;jG!3zOF7s;cKo+WM2~hr6&U)@&~Qr8k@B_&0szVqBL4CUK<<-eVBqIidk2)itzL=LPuIJ1$ic%iMyNx zIc2@!C-zSFI`Sf{~xefW72lTq&rB91eor1EL(umBMb zf?IcjH|W@jsGgKJ15UlDP6DE4pQ&H(%^pr{U@d~(;$jZDv3;ULyFqZk4vIXEdLQ1r zIVz{}r7hT>t0?jWq;3#(v*mYEnABVoL>aTP-At-*Wb3A@@8>}nrj1n6nvDW;PmYS; zOuy0^bWN^!W{q6rw!kaK2n=+YSL~us_i|@EYzHE&wf2sOPm~SP7-(BeY^*82=?qyc8%N1GF3nKf{#gfBl#jC4qo>09hhdc0uE7sn+r@K!HIc#=(YL2+9M=ZF zxE;OVG-QtB+48Btm9%_p|Il0PL4SimZ8nqZO|F-Q0yRu06icgDmdE-RXFzK8!RXg| zGC=~!ZOXLhrcb4bxH`!+?4O@Gvhn>$LTmSJqw2mHzpNgWe`f=+)RFnX9k?$ z9VW`RY{qqF&7U6~ticctaSF{j2Z^rsPhZ1Df#dPx0e~LL?fCSoh@}UtsvCBPmkv@5B%b)Yq)Av1kvCetr>+fxCyrO<*a85#y zL`c9nwxViaU4%gd2j!E>>%(yWJAA?>iX-5$SIz0KkWDb*X))|E1>D}WcNiPOr<+m< zqV+GYEKrofVpxoL%#TCBYH7-vETWY$e#6@&U8`@e)R&o2_oEz3IYCf7CD49Ea;1Ab zv+gFKGcM)bFrhO6r8t_xjh9!wNpEUqKmaYPbLuP9sBl^v+$x3&XSS~tH!jnouaDc6 z610b6|AG*g z6y*=>D}Q98zMur&l;I11*AGCaWnAki@6tzXH|2z1{>U|Kj6=E=HeDY{J@nvv`}Fso zE!cumVQl2!fU6-?mEUBqu;3BAA z!;2#AGSGVLt^z7#a=(Cv*IEOap<0^7qf z1+2C@S4C%UgU6uxj9;i*FD!YW%N0WG1*Frc>{T^9^iVbZzwOnV{M_NrCkNePGBp{FEPmdQ;K=aaKVjtxd`rRv*N&-~? zk>38!K7I0e#Qh6fsWG+ad`L0QGYi{P<5Q|5~|2OMSP!VNVqnd}K?|%}uh9WC-GH2smDy zog8qsrtYmAr93Ukbw?EqNHfw|%}9(?CGi`9EUEx%mvT#NHp7?MeB3&^VbNF+0%H@qhfBTKQGeAGkbna`2>%j!jyj#DJ zYX2~lO+|j2ct}k|Bw4eH^-&2_2G)IMyHrbG%AwC98*B2l(0u%(;k6C180MFIi@B+p zp%Xirs907~)hCe3O{G!TtKWd9|1qM+W}~=RMLN!Np*QY|)AtV+!oUuAVw4iC?2Ok? z(;1z@%fSg_EO<}EU=r!kz@|7H15Zz!!@bW8y5~GfS?^GLW9+J&j8hXO z3zK>+@tKl%3)guZ%n}`02L`3M({62rOE52W-j9O>{qD(Fi-Udy5Fh`w`!=in*q-iB z;AQjk_h0EyIw)!LbKE-F`}EwXg6s8jxmWE81Dbn#oL28b-90Vixh{+F%hgFPdmPpV zQ}@^QjIW=s_Du8uwHS?0&f8ODTVl2-ta?S2`W~Hq3G@-4foT}5q^PEqtqJHir zQ7iX;7wc{ATc3?-YH6h2`TcvzZS(1qmem2sM>3Dk7UG>zYYALLksPq5wIQ!o9bO%Y zzQl2t?J4MZ*<~HMzSg?wsV8(c3RtEVM=@|dV4LBH(O4UVjm<=0bz9EVf6^A|jCT8+ zq|aROxA~;VCg|6coLc|(G~`C(vr|M6%KhN5{4K+3y0%>Ri=Anz zToQ$i6`jL+Fkr&ZR&M2ki75iA0G^(?dd2x8!4r7~2kTB;9%@-Kr{8b??E>jted{Ml zSvCFZE5e+}k2e_Q*F3^0WgWK@ZB7rDq@ruhBE{zdLhY-aY}JmZxP zI-?lI5pk=YgtqSY4t?D+oNvgc%K`Uy#G^v?)y0`ZMUs91Zg`()P*sL!N(of43<-!uJ!5H@I z)m4&`V_4`n>n>{RD*ZbU+#WKNlEt3Zr^}+wCYX9o=c%OpD;EeKLT{JMj0ML_+X(xO;^xvpN z@J8(aKi>G37wi8*yL_+P4Zg`$hwujxnt<*EXVG;4Y4=8d@E`KYO8tM4PZHje&ME)> zKfve#E#O`pFhBbt@z~|o`}bnhq2A7u^jC0MqG-6j+HZ8pa@ZeyC9cfl`)HgYER@vL zU&Px3?pa5^rFqgX%Q93@_Y1wT&F~Ao;U{wyxb48_w@T z|C9d(3;(OT|M$!P2Z6-9dHn2~@AXf=SS;QK%=btNE=3GZmFm>KG~ML={86%n(3;tfygA|>fAGur$d_RHf^`&y`ar+TesRYaeFzE8FF^s|(v zCWauwD(7Fp(Yd%!PCv_>kpYjHQY?1~s6TVtGQ^kUYm5#XaI@k9e2|YwU); z_^cG^Sg7(@pH;us-Q8(SfQ!#}9&DJza}5k&3SZcR1iilj4F7!30t^AY zR%QXp`RxX`(P_nJFQ7+d$w0};vc|S`z$r_$mJG5uaqV>dSyt%G z{D4HE<|#P4Yo?}lvY+Vh%gz>dh5a{0)Er%a@=4iRWX~kFYUu8{b#I~;r1Z|()Ht)< z<|c&Gg4#5O)k3>z*_dP&(Vymk`wc$gtY*y+urK%e77_WYfvs&^;Z;~0<^Xr}1xb$1!fs=^c5XAU5M#LK( z?`KpK^JCdZdxtFgKTktRH4(5NynE3>_-^GgL}hxZ03TEi@4pkLvpiW%{o>nK#pB}) zN%$c1RLz@j6p^$&S|u;4%Fjyx{!72j&tc1yjOG`Y=m)lUe?KuWBlKG7B?{~eJ`4i> z8EGxe!9=%Lx29^6LdmrGb(;pNQ=U;%gA-R(2okgc!0Dw@;y!o@R`*w$Bon`Nap`0l<=S>Bvl`bXBA0c@$+z<3)V>y&R*y9t476FuM;X zW^5yDCHDTXHzY@+B9zh3f40GScjueGn#ZNbX%fGt(>j;1)l7WIqXw(;N~fK73vIl^ zxqBLU%0$tTlrK#^)bLei%ZzmPmhsNchvHTm{>~$;ZnY#UWMN@mg*xwt7y>j;f=Yan zZFE<@_;>-}PQ9UQ!nSct@nm~=JnN7pWnd=|u#>$u^Go@mTH!JC<{`r4_H9CJ(*eDA z13-#X8)&(tLP|M}92a}FYa}B>6Zy5H8QB&)RXTF=C2Pn%SJR%DpB}EoV|9h67leDE zkoPeRk3_4_E(L>Vxb|y1fyaUF&=2i8Lw|q&^QwnCzgN?Tt57HYXs;;~taoB=DJy@0 zgDAKOwSBQhN~rMm$&A}dk=6jn>Lh+Mi+*T$^E(w8V=SCY=H0x@Yk4+TX#ph$CNy_c z-j8N>&4a|D5W+dX+a`Q^Fm}mrqo_=VI&=Z zWSI+=vwX>W6G1u8BT zlDz_e|T^$lU{`(RkHZni=76%Thti{`O?y4wHLUoU9?AaeIC8z;q0idCR-&{|>UPyJ>$lG7;l43$5F@c25fv)A3! z1ZvfV0m1cIo3$=`)nY#0-l{&eL)l|J$d~x{Q|;j0{#?tODfju8 zi2ma(G(lHp?eZL;eAKmQ_T(u6y+WZ3{3EyN9b1P3j$)b7pT^TC(j9&9A+M#*FN&oS zp&7jDowtC*7-&vU7t1Me36FN=|Hzc)r&jMw7W7ByL?#B}L)9BE8hmbg}^?2FDATD+582q zdX@jS*lJBpXWVXWa9b(+A_C>P(rXb_l1s{u*qrssuX1`FIbqN**|B@b%8D5f6(tKX zfa0##ew51UDBg6iwzhS=a1z9cL~BhLEDyGk6rlBn=;`UHe@}e-R&{$j2Kot?nAl-= z{$pqKY2HQ@2yTwKiWUv^XR*v{NuagNsG_6Dc(ljF>HPD4z;5s)-bT2_tynE`BT;GQG*u8|xz;rprTgAf$q(^_+mq1tgT68^05I{_*2Dj6wp{nWL7g zxK%)!Sy0J#8=iw4-eY!w@Lk=B$7WcI zU1|_H^SSQ{37b5w{fOx5k2DezF9#dvE$ud=Z z0EYkv8Hl(DVP71KNLKC_2lKHghQYNHTpA4$fv0MI(Rs>iboW2j<7g0k4~rG+qSBNf z+DCYB0wjQv;loaYuRni6)6*=wz7oF-9F|u~D!r4AD+ce=uLrt}iyasq?r45@_!u2V z3;ErrYn_(+b`&zDE{S=+E)ns0UDggJ`b&@z;cI>Vq(78}M{PdYaLT`?I9>Z~aQH6P zugu3l9Ne33=aE%TkcH@Gqm?dO#Io+eB)@r_dJ5R+`KCP{kXz~9>x|i=Pgwt^Z~9eT zsz(`beI|*&QA%j)bqpqhRyBfoMZMNu)4{3}^MDTkS4J%@g-S)d2GZ`1h(=W!km?4I zji|{<>k<$WR#;3fF0{o;OA0q43pHpQL}GZ>#z9pJznDcQasNZS%mBdj+;#}LS0VTN zCcIA?6crE|ysz>mAeXoaS zg$~Cx&9_G#VOwVzULBJsIB!0Kf;qC>%jW%i^&)B>9t|A`?Se+Bkbg7F;AOY7_hPXw zgjNiV4+lp$@4Nv1XLsh#D-nAN8Ts%=3j&Z=X zkfDC;H8#Eo%|KdR7w_g6aLCU8HQ$%F+VQkJJz<>u{>_myGcC-?zW)Bj?kwAszhna* zOJjXLmWZh@Nc`iSbamP_puL(1`-&?AkN=#3|Lf8HC$YHKE(0=J_?qc}+STdhSCR`} z+9SYUA;?l&#eZGkaTpxnNI8c7C!dA}z$i->VM`hRx`4=IPEhBCW#zww{yTvN0|tNX z=<1aGH%3;(5XfeA$*2V({w;D0!MQ z7{P!^&~)&-)Hib~+=KolE@BSoeuknldEg4&6bhd-HG@biVysGj=>T2j%5UG^1%o&L zAgOZeaTp)E6t)|UQ~Ct0M>I(XZ->D@(hT?dLB&gk*hm9lQAsf$l8|l`B|#nM`T6oy z?Dy?sp_0-c7dLWZ|CkbPN;Y*Q%f;ATfzU7RhdpH0U3`q9`~&J;eg5`7r=S+b$-mN* zzt9|k=#Jr7Y)a&Rkv0WEsdVjss*ij&19j&*#95-izvmZRwn+v@&0FX{Qx3kLHmK>0 zA1tjb{(BlkaKMdot;PaIbpM+5O$|`jD`FF-`!7KwSAd`%`lj*;=ig6)?ijd$qX&x5 zg)J-dE_k_c$D_7@mH_^`zw5}02k1PddmHmtja#n zGs^PM7a{-m^VL)YCT{ZtX@~sxxIWzkcjo`~TU&^MyRaZHbKozs59F(A3q+ZHM#t~-rgpo zKV%;o8u`R_>+z?6rjEWwwRDb(=N;kh4v~LQu%E7w@G%otF!b7c)%DgjEuQNC%W^!z zCad`V+6+bTFX@r*SF~ckIAw4Nxaebc+EG1;!X-`S|EQPfUU6=T^%Vcu^!{2RVPqhl z?dRD1UF-dO!v7zCFCFpdOAwXbie%k;QvH;!wK?8N1=;f(4{uMSYkjLDCMTb4EsN97 zJOGoTcI__d^T$14RhrN)`~~9S=2bit+vGF$B#5v|{^b$-iOsv&oFahYWIaO26;JQ& zOLDb$IvHwjbA#8S7oLLuDM!Pot*H3!^uJ8nr^U}|w!C>3gKFU6h?D_DqrdkI3$UKc zZL$E%p+EfXmw}S)2^5SD5m~13QbOJd6&pqA-h}5N%?O=(XU_)UOxQgP2_dw-+|ySZzJX=DY!x|*Y`#*p&pGKo(yVk))!x13KBMy9z~x;?`3O6G=Qi6 zN{a19JJ%n96@w@dy%%W-p_&c%4>G*t+T%9-i~ZTKgn@rzoyk^Sy*iDr>QYmNlgeK0 z`h(!_zHhJgqDOi|e>UQBb@c{=>AQ69XrsH={x&-lqg zBuR?@3$h?v>9Q+BmOoq&%Y zV)g@{GrgF_=}G2v>!IMLxvU~<>|o7>u*iU-+8_m(GW$<9xBiL#pUkddek&y^o#wM! z*{-RZ6q;3a5E)s?5~dThd@#7`KOt=Xu#V!h(I;Cp-wnd;vdYj%=|L~N3-+I(4MRuC z8g_YNWw@hqJH6xlZdp6wO~t44+c$hDc&HECo(bzr_gTZapCIqQD*TJeFgH4l^+hI|n zcoAjIb|Qi*pdx)VK2c?H(6ca0>zf9fi_^dke)8YEecfciu9-@ zWi97mF0FBl+aEc^&bFI{*Id8IeKP+-$~#fx`qi}|VD&Sce*TAPeXrdBt<*71 zK#kT%1K(A-9m>77G{F0DD(py>Y4%)r3)*kv{e{AWGR+;kR~Bn7s&CHMpN3*5I|fRK zLrCNp6cnK3*g^7&CcIHf(f8)cxt+4R)|qz-F#kJ#`ImS0eck3wll`ZE#7&(K(Oy@j z@yLH?J`a=VV%@26cOSPg!dV%eEsybU!%}8as5h~Jh_SOi>uoH$%p{GaHjHf9*Phaj z@{~?oo?lZeg-JsEY^LKJl2HQJp|3Ou#lCV9DQaG#68`nkNWV)0Pgoy5jIa^dfN+6zE1%w0^3P;7aT0`;6tC6|Y|KFD&cmF$tAedE z5z&uAEU0nf7z8&;KLs_bX|`I0tB437U6t3Ba%XZ}O|#7!RW$WDA@opHn<)CCp+vb} z%ihwe(S!;E{IGM*qb^w%DA^OB;IP$3!0Mr0rahk=~^HEh;p0XUYN0XQ+53P_`}})(t7{W_%sqqre&s} zW!{8gnbBLj-5YE1Ln?)x-^S7}V=j(ZXQe+#x2rs5Xw5&gmWk-)9OSwA-3;{hu?_U*24|si~>Obb@5|-jINIsG`Sp8e{mG|MLcsS+s%s z19Kpng6&``Sy*cB4#H|+JQ6s(nyyOUiLyeh0m%;;Y09<|509NdJA^jhy;OeWU z@#&hi_gUk(k+sxpl#`qm@&U^)>KuC`cF(wrIq0%k2}Q zyN2{MPVNo*rkT0qHC|k0bKRe7-biJ+kVmP-!K+)Z2(Gtwrxy{v!ctg1C0B{D|7%h}%h9l4h`;L!~_er~6-!f(niwpa) zw6KRf-bHR9M>R2|qP_!Ee`8bANT}7!adowMKtKWk+sBKY9%2BN`KXd_5bGW#L`OrG z9n$wAKI}~DE-_=FfUvDW@>k!Z0&V_+|9qsM{hDq2h2_jmP^}-gTdG>|;x9dZRg_kf zSjx|`TK%J+%|DQfdGP1C9}-!zrBu0-0DoXSE#SKMW6Fo=W-+sJzJl&f6Ti_m^JeMK z*Nar++>Hxok@<3}>q-p9$_nl>XFKPf!d0k5BcZ-TU%Sqk#0$PmGRcDf>p3Grk8@Ax z6)idXz0b5w%Hn1mi&Sq#{BAFHMw<=iyf)?Z$0ju$NNed&71gXTjpnr)OkV_BJqL&F z+F&NfrwoDwVJ}Z}^MYDbv)I-|#fU1cOx#ao7u)5}Z#Z4CY+k!SGS8VANEzpPgC8~j~4Q7e+?wp|Z7KUv1V)C^$Enq+1W2OK@ zgib&JtaNvgw$uqyYf)UDE^~qkpVi7^rntrKXis^*o-dLUc8YlCFjK@S)OMVITFiJ; zu=XftB``TtBQ`=dpaPtX8VDR&pqcJ!N7^i76tr56~-NME`L?R>Lk-$>xna%wB+Ah8GbsgMW z28!N#_>B7`f+x?#nkU+Ltpb`vE;(QqCp$e%2{5y<-h`QiDo13G+twLsQmq)fK-B`c zclMGB>ny9VN+MhcJy4l4spi|uw0yH6Bt&4kdLQv_M=mBfO{@+S3n5&-Ic~OKOM=boE9*$`vsYJ9y<)bU5OuP2=x$hG1iClS*e-PBAkt*mTvx`l~fbhr8 z{^Zg;<-uY_I9ff4TdD{_b4(O1viLwbi zfcmcsVvNVhzR6h8bZ0aZO)J00N%^J*i1pwzfp`fml`U>^2kUs0#IQkZ#R-g%9G#<1 zL;=}jM$*BxF=Eyi&kY)~^@JbEg=_7M_7)Ss~O95&B1G|D6%e~V*} z=!F)1=e24)KS;3Ze9*}%>VHB&|M|y|{4AI_kBA)|6V})i=)hvaQB#(z6_2sC{a6u! z$H}n8m}OgMbg^>2BOeN^Cd+BS&txUJ8dtQB4{YqGVb9`yZoVmv^ELkaETN1F4Q~e% z(<2vhxw8%0&C-sViJo&}U%Gy;CdQ4+O}KH>CnI_-Ynsq0mYWP5vU;q9y&`5aYAja7 zwLU0FGh#ySD&m?+6efY(1$j3ii7S*Hxh`D%ROwXL_HhE3AW9H+@a}=+_6G#3eKk@B zDqy!9JP|+$pmq&MGXNI}rB;uSA!4<2bOf%d!1W_?n1g{1o8;+Fuy~}2h=L+_*)jK~ zrl(=O8ORjU)YR15gshtr75Q9@W`V=`YVwr4goK0)#d5ABPpx&M8C4d)zxn0|oLFTY zJEmT(tsHJmO2@LYBp{FB%Ew=Bl6S{*Z%jMQMqjJ4n5<;bcjX|V^PUCE74~>LzZg-f z?ge;OnYco?3{1VJPJ3bby=Op889a*bb^({PoI2} z!sn};{QTxi2k*`i_^Fz#B9ue85Ie4Ml)emtkh}lvEr19kPAwgItE?(5x?%;g=)T$D z9&c$i)Y>1c2Q{8_>YY2-d+pVtsu{eBdM)^>GWsGY?*`Ua&%K0ySdAY#0J*KeZfK$v z!>o|mi9r4NfCQ?CiH%_Dte9DMO1c@Db6KPeAFje-r9moag3p#d=8o3udQWrt@A zz;kfS_V(yzX%0+C#>+u~mV3 z$%`yPRfFp9mU=dUlF=tYXSy9SfFm_yc8~v9!+-ONe zw+WE;@rw!$42;lD;&)Ot(&(gzsH?}_iO)oMR#1RgM|q8?CgM4PQ+k5hjd-RTSL0Y( z*5)*lD^xAC&01QX1_y)p2#=-H5n?NIXbEL@@y>UQ+h=66^%axl;W;uNzVcYfeF)lM zx6J?_D7OQmT*`P4Q&2bwK)JkQ2RUg3H?Z;12BUC)fKOBR$bP#(3|5-IF==)AkU+Ho zQZ_usCb701$#oLF&)0~muiq{}W%n#C>ElLE3pjGpa)`TJi&tzqJDNx}gGQabXdRvM znCfz*KRp{DA{F(Maf#=~lybqeaMtrR5I z1dw*n$}pm`2E1Vt^$^o2x%TFlL}kx_CpdE^J%*yNY8Hu*Zqr|ogV&O7Zf;$l5+hVS zVOVJq)z)+Gr~?VvingOIUxhhtPw{a}NVcb;kWhGOaE6Vih)5IgxcKTD zB5y1O3uS`)Iu>a)gC@>fjIJif$~p$%o*6Iq@bF+nlIf8f7H z13t~KGo?XiT6wA%hp9eC8n;3FJtD5iCT64FM5Ih?EfY5;5oKhwKtZ(f&Dp5tLd~k- z2w*%O5)i=dB^s|x4-1y=Tn1L=1{C))ap9b~s+9W1$YJ<x$wBZeVlPMo5Tz)M<8I3vT3ppq>$3nmS;vzG+~-Ee%gm2Gr7^X*#(^h@*>rYx zzJy^`EEB&N@4lxa=)`J1L<_fN$Ul=dr`-1|2xdh}m>&)~E4;Mc;PT=euo_?<0D7@8S`39cW-2spF8PSi;)c!Tx^(as3urjH z_azs0#niYu-#K3<27@`!GT>QQ1~;0(M48hffnF_N6}Sp7;v1FPOEjz`N8%I0*l_}I zHK}Lo2iZ;JbW#cMiN>L8Ev|O)GYOrNCgYzVuzxlV+Zm?F<~&}!8-3wu0FiZX+;G>RAexW_8>OjjGYxtTu1q5n zxjedYFi{6%Y&URpge)c^iV+c6*NM3va{n66NGFwnN&;8-m|~Y2S{cvv8?T=50r|dJ zS%eFX=c)CYA}mK1jT3W(07#bzqL!nV4rZM}G*xJHWi@$*@e4DsjCR9CZdzbWK;ptn z(%3jpDxTad0*}P}6_+M`N5-9mTdUBfdnD#v36u^_X%~=E5geF>I7ClO$DUTyNM3*x za!ZVocWiAx$FG}@CV3fAbwK`A*N1|7(d2Ue7G}wFno7k%6+xcx za4B=o>6Fxn`Zk%-$KixY9sT2YbriR~pBnYC?(lLlFz^;DQ-)`tinvCs6bmb4L7P5g znOuX(Ffqkl-}m84m@4|>EP+YOdu;D)!Z6K2+Dpo4FX9Z8my)2zPVQAlwZH6bWTX;s z5mv&B?trwHo-U`xE=ngV6{xcZfe|()r>+vCx#C&d+cK(`8knYWtkp2rS&_L)BBtt* zt){=;Gh@9PdVxVnnMO+TqQGOUSa@ssaNzSBug(Bwh^<(l#cXnU+~P&lQ6jHwx6%jLJ<8=AzP%f#q%YZOp^s2Na`-@@y zPs5)J*V@S``AKRnhZ8`5@egHfnatFSEwr{oEq6ujvS_Kt+>(8CH^xSrAqL6p|Neaj z$L=mc7RzG$oMPJhP_9^HKuZfva~oZT7HtiulE7{q_VD;(x=dmEc~kFuLlUn8jVYtmU_PD zdX>Df7uE-7fv5gjgk{m+10;}FqgdWHPaeFmjU zIN|BZ25B^-Y_yBdUE_}<28Kz5eC!w^3Dd0g#r z3N6wO;$mP+;CIp~fY`-vh6G4HLgz%;@8~?g(dK!|qSYhpcG$bzvqBB+0d|j;Bu{=g zd0loO5O{Tt+RlsZcVRmJLkJMa^FH+xsr;~rlDfGTP8N+c0;eO%% zUJ|D*7{YJRo_B^41Rze26}hN-EyJ05x@JSC9r2xMHyREOaoT56Y0$>mu|odyueb5d z##pJZL#-N<_8%tfN~D!8_ZZDq?^<_8#jvsx7*47b#APdH)`Ja5&~$ss2OHZDXoK=T ziTqGxIZaN}s9mSn;EDkxnR01m4YjMo?4ObH_d+Yy4N`=n#Y3C z*%QE4=e>Dj`7Wl3a)s$du9B1VQb)9)5BcrtzE6Z)e`>ss!*smsyC zJmGe(@^&3Yj>WVId|2DJqoY|t&UAI@=#1J*bx|G!<-nqvKNdS}CLxYS12i$r9u)9= z*7$Mz(y=vzI)UeYSV>l&@GOt6$jI7IN+cFdd5-p}e~CWtKG%u<&t|{+`qG{0(?E{f zpn71%Ybjvn-d>~~OU>97*`|Mfg7C#!;+laa#;BVuwsYeeqfY6f;ew|kk+dy)E0;$H zPCzh&U*N12>U99boZdfhUdv?UHkCO&oYdYyOzO@e@^PUaD41D?7iuXF7%WGM(}95w1!|Q zXjUdVIXbG>mix=lL`M{A_F>+xqYW@ZQao{^-Q} zxc>aH2ig~+pZ*G}`tnet;Luu+)2LASLFl6U13>EK%+AcP_?mEkEQu+a_8JPOohv%_ z>&8V@QAeAs%tx$E{D;qYxR4qdMmqB24tvKv()?@{7g-0hkr%2`t>SHR#oXtI0h3F$ zQG2Z09>-(f8XZp$=7#;bbqXmkJa;Zny&*TxHc(?Ob-gWHgkD=0`5KMr8n3G&T1leh zyU!oGWUxG=Jh5p7qHz3%TQR$uQswmb`)Pk1BNu|)*m@1y4N2(ZqpG&D;$Hc#HI-ZN zGLNcO78IjXGl+2$gi6U~q2qHjKe+b;Xh7Ixy8B|eEY7h)BG|e8nP5PwD_e+Iwb64f z#dD&Vtj=s~3C?*WAto?UX(7^izB67npYz&mrH7wBT?bbc6zHTWSt~&473$SGIjQ2B z?^vNg!AA6nSQue~LV5-fkh<))&?G&Jj;;pK$@`t&qez+$wzjrm#_Rp5X8a&~kz)*s zD$sNiZ~f~gPEqa|Z*+dX-Q|Uf!PD2K(%13~d)_grCEvn|r`WZywjPLPawBrmT;TGC zxBlRY#Ye|Z7HTl;OD?dcO}vfcij;j$q7ZXJw22Rd6Z71jkS4f>+hng zy6YRbF{|nIGuFq!Z!}z|%Np)eChEJ5Kip(KR#ivMXvUKZx$4i0^z%QTRk>i@Z%}}6 zFV3{MDIyH=BLriQqSOq#e4a_4u!biNr<_mQIaPTe3fJG}_0ix=b77h6i*Awg1W$j0 z=+e^W?i9Atgp$>Ev4OIl^|ubCoD5BjaKBBwMRxI0`M6yJ8=7FpnCPtnapxtG8cE z9;P)@%aeV;yqcMz^!5>VUUIiXlr>QEf+<$puT7AFTLo}mZYMj<1v=`k*$^+B$L*o@2rQRs%a z5Z@lm+W?@DJgLp%!n0oxlpQ1kRkoe7tr>A|SdI@jDHW<|%j3ao(u2hdkA96#`Y5@c@S5A>c7M zi;#v@0|^pQ+-QcqJ0r+J6_-`Bkvzg-5=nX+-CRY4+30?a$LU;_>|kbxyxPeL?YT*8i!>VA#ehQco5=15pA2*@I-^v< zG6L0CX^wYvWla1I8rE}PHC>Qr#Kn(}_(X@$4T(CXmmo?_E#s)-J|Rx@oBn=6CN+7( z*V?0Ap`^JSU<|$@ez)4a{Cy_?T-18-!DaTj4@=oWT${0N2gYIuuiS@VS!WB+X<64U z!%j5Y1ZrBp46Rm!;wkmzZ!jq$qEihX>+ujOUa}c?=c7$+A`(s^p7|H=V;f`jkv?2f zp4*C&m*GNNq(lftI2g&QDQO;eYauD>ys0%>sd9)lJSq<(XU_kXW2Lt&G4cB&B= zM&VPz;?r8(F`oj{y=V|Ypkbd%?F34QyG*dd_O|}>AqgIXQMVWESJKfZyJ(^H8H#OZe~uL z8$F8&PVV>-XOmfq{=vK!$VyL1#uw2_`{cNVkTWWAM!!c5!6J6x0;EN4gJdhS?q}3GoG*DZL2euDuRi8>pQzmW`X2L==v9>H;6!nUu)@5oCQ%LF!{3=4spC&k8xU}8dM9}`8HQRzgX z2JKwM8msBRN6+jl5?^#g2%R2khga;tR5L2vg@v8qpkFs`!$4Kslq}>?%)CR!87|-|PhgwG%*Umabc{$Y8mUsJm;s?w= zo_m^q3h}e-)-3lYiKIgeE2$!*XEAQqw(IRKv{{8aa4))iUVOO{nM|Q9M9iBUxwBB1 z;f2^0XMxPWz_qPb^m)%-n(Iz2k&JY$KiCoW$0=sQdjLy1nQ35B$%~SoP96SqCY5z3 zO0tC0)yuY9D^ypGMi@!5VObF^eP-?rB!Co}$wL|gE#^Z!Jyc`|0QwfrI z3X=-Dtk|KW3~;X8akm}c&iCRbY9K{!hR#1jSx!Iu5h|RlMy3W%EE3U7D@u+vwX`k# zqn|Q@oAt@P>etdkc_d3HU)o+AYVta8Kj;`hit1)%^8826mx%t}cYcK#E|$CPlp(Y| z?Y2R6+1on%XKAhEyfNMd*M-TSR;_9EeBl<{bMCA%PERWx8}EU{sMOb=mKIE=lChfY zlAkVoN2ae z1<)-Kv^DrFKupV~9y!1R7s%Z#jS+TtZWzv>U=o&o#*6Wly06%Jb3MsPoCgfCVZb|w(EG#nDxgpheCx3XIf zO>?`SBt$m;;w9&WET$WOOEZ=BTg*JH$8v5cM`a41T$bqd2bu?rXUI&?IncaP3Uq)@ zogaBN?i`!8Rd!4!Y9*OAK%^;|mP8~|Fa@cu+aP;hKbDxxwOEqmfyE;8hx=jA2{C63 zTHGNR%~Zt_nL^R)Atz3&;#+qDg71YnSxW{--RGXHm&1HN+%H|IrI+fCvTaxEd5sIs zJY-7ADoTM2`D{YY_l6MXXOFnCx)a7A^Gq(g`->fupqp>3Rme?GMCqoQZqS-7qib03 z{BIFn_w{sJMA-Z}+LUk9&~OVqjGuAXCXliyExpxw zei~{}_!6_*-~%&W(tU3TZLPXJ{=cE)1z7F#VGNB{J?r7mzVGgEFh5(pqx}yw^mh>7 z1nk3Zvf^he|K;>r3y}XqBTJwDczRu7A$3DRQS#7vgwN>j_}{LFMpy}Tw%+r;LFe#h z()Uzt$E^RJ>|Y3dkq!RbTKHEO{2gckl9~VHF<5<+K+wp{-SlorY+tW#viw_t~v zKuTK|Arvsa=rJTbirQ_Dpn?HST-Gb4|70KtzR7Tn@Bgs(7C=>ZVS~6JDkUA#9fEW# zap^8aknRQn36)0akVZOGy1TnWK)O?q5((+rb5VKm{r20P-P!ri{&&8aJH+qad*V6I zc{=_y?Ld1K1)DyS_>jP{%*sSN6_fQVHanff_x@7h(dClpV#k#=cV!sts;3IO<*sEM z;^%~IRN=5}NB4?|qFoxenXBEF&R6ZzFL?SxKG&DIHOAg5cdd(TkZGm#aF>O~=~4$O zT_rE@5_njKmmfv$(vM_Bw=VB0cMz~YTv2TK2*PA=kfIHgSG4B8W`(0#2`KHN_CBJ$ zX|q%vDc>bY%#{t|7?9kwD{Ovxt9gT1GhPrSH9ko2_$mWns|PO6OEdgV=VOyP86Vc7 z1E6u;k5GJhYacN%*iWElt{|4;rimy%R;Ma=dTe<93x3HYt=(7mWTyo|q*)>;$-Z%a zi~F)d2h^_hDh)PxQ=rOi)wP%WLQHmfdb{VxeN3z$@s;{@-Mlm}GpAUeuvqj8G@Gk5 z=V?8%&VBqts*TDPyOSyow_KaOml8xC%Y$m-`w{MhS8c3--@)*%7}evV5kJo{xR^K5 z)AZG)u+&GaCJwsmUX$rzVq=s-wlD1IMwbN4Jt|&TSAMk)Eya^XfhLnAf;5u9;~%47 z(Q(N?y?!Zhfc4M@NPFXPFSd-FUwIK@6UGx#Qc6omaC0B%WICj3*jC}=hLnKtnH67? z%ed<~QxL(MC>E^$Cj{HW_&%vQv(#>=%47VRhlkyQ_rufm5|tc=n)^PA1Yi_B>xi*8 z-qfyRx@od}hredK|1gtn7Zy}$g{T3$+yI@}RW1jF36}K*m1d9a;AAxu|7gf$G4H$@miA`(UO=n;Y{}$8jTajHZYAbpw5oQN{z$ ziK?IKE8G<~77s6eya1Uks-r%#Aa`#Vg#R>;;}UE1PXsBXVHp+$1%)a$GUTN&4K+3X z*F~L>!W{b_IpN-v#Nh?Gk7uQV+Bl^?-!yuWGr?!f^{ptOdo!t0JE7gg`t;?GVHcHD zgLAs0;T_<`oLdEeNSq15|Fd!rV`|cTr$lVt^+W%~)X6AfLVoT@pv~)llI%SGxZbVu zd4u`mTj$}=MwqdkD&teYIq1#_^SUd2KZT(J^WZO@E)9LnD_p{;-WN2Hj`SywDo@1IX!-SqKJFZ zJBd1}BX*MjYP14+m^9Xj;iYAR-#9>ugou^(bR{U<>eaHWS_;cY0fzJvy93$PQd7KX zm^E?IY-q6LFn#yy-|1KGLOZNO{uL9|>bMU^ouDW~r}x?&fA&be;_T(f&A zx$?XE&M(q876%qvt7+4F6+H~4_;xfPTc=uD$mb6bp?soY1`M$A-QTwEAF2t0?xB&M z)0!9$J^w_&L#5b#YT)F%M$>=snQ4$twz?VCPxc3r&?{cR1qN`cUWjMhO8?I6|fxD^vz3a(TPJo_(p z;{RketjIJ-8lR;+f`SzXc3V*~&a5+svS8Q@1h$|nCFBw;Bj7gWOcva^4qCK+ z5pXz|M)+3&!Ix{#0aWJQfK;9_V%G<~ z0kaO4IAS?=75;rWya{lAr~SVO4vT(G&Pl{MEc*d<;z zD1);t3;P7{7o^^LX|EX-R*&p3;80&Bn-)X@oXVxl1owtD91;q{hqSk5GNAvje5<=~ z@$4pVsiAm7gs7BoW;o;UnUP5Y=k-R3@#+G|8lVZ68}oFw?*NHX zg^;tnVd-Z7`X~Rd3{d@{k+_k+(GW^b*f3cCerO49b;({D$KUq=+F~xy6Zx-)5Owf< z%UaWGO;W&JWd>xFje_jv-&8>vPz7}>H9$+Q4bcOZ+#}I(?Y@DxOF#?I!T(z7|F=+W z=!MgJK3!PMwruyCeO~9BCFs7@BzT-AJ!bU{!*w1z^roF((oCV*(!UN<1}L$4Q@IR_|K>Y;`ExzZ6D6Mmngr z`TT!$-6A2*Z3fKPYw_cRa15EK$&m@8!kM8jA(awRAy2Z0@M_LlrhI0D46SgIN2+P8slL;$73@uq(_ zHY=b5oGQ|r=|?$65C)-(gNT3~wh07s{;2yJXB-yJ@6q4l`ID$a5$H4!6QK`h@ehnauJ3&$ z=13Mpl6`V_$OzU}md4D2pXwh0^b#rl&+*4sZ8A3vV!^TT{ipnq_>ol7?-Oi5f%3;W za$A4EA4M@%xNQMkFT;(m&>74o3l5fjDUIc?BLI=f4Lwty zgnvDRJOSUAtuzHK(yoomj4N@L73e*u^Y&;PDCh1Ba21snDH2!b1WCh|u+)i)jt(*H z3w?K$^>%rTRX93yAM=<{6aM0(PN0HAu}^jn&tEDXw0?q}%j=b^Tv(_a3`93$zg=4<79J@dZTsi+h>-4K zU}D-&@l`=n#0`8Q&PqdVX1Nr>@$7li#Tt<2X?nuxsX(^xl$Ol*gpSr50}FNR+!jsS5sj$v{1FD0G-R z92Hc**>Pk3f;#Ja_ePL9TA6pR7OHKsijcB2c1`snn+8e!mJk}0028=e`Sl~k2S{a# zEce%my1QqB6=cFs{!Q!Jz|QgC4*qokNOhoOk*%@#`uHX zUH_~JCf>12&c7NXk86 zcs0U+vOv9;|0;q)4@jW89c_9nCH`AfSA%W5ee(%k@d(wD#dZEmiV3ylHU)^i|2@nlwI(%(mfgx-?;QVU za)4;m&{A5SxIv89QK%eFS!$wqT9*r^7 zD8*X}F%S^}iQc6@X7<(xhniO3-r-_Y`$RlYu2IQv*p(3{weUmWJY+daKIwT_AIR5$ zu4bR2!Kr8Co0@GJ_!p7|r!hT!M=m-f`c$o$K3$$Ei8I%6cljwkmof^Y1&(s6#;SI) zG1KAC!94_ou17hTm>3I-3oUEcj!0;#&5Tc84FX z)so>OT3W0W+mpJ@dir`1=a!mf7CNP7pEWfnm%BJ>Uhh89)eRH)T5#skTjuXV}oTo}HZEc6b zvce32J_$qd?N*?`D+%93cYAufFM3dw!*ngkyHL@Nyt$~SFTXK;(%s@G5Qs;ydfMtQ zI#qL@r#X(p*4oWDy~h=gJmN0*)4z`| z&M#5LunJKX_HWlZ$@_RwwY1ircG6%-NxFV{v1H`3<-wc8xzkQkPr$Qt8cOj4N#l@iZHS*EH*S+=WuOyHMHrvo4FcbXLnriSAsreWIk zPtw1z8B2Zm><;779Ti#mUhwWqj{u>PCwyb)2fLi9Oh~tT|}fUUVACQGCI#RyFjcQ!>%^ zk?l$dazD{@X*ah;_()`i3}20Xy{nYk?WG!L7tqX{A?{=(|KR6-lufZEy)vy6C=(v$ zT6XxIYn=T@I&!0GkIK8H-@@BnpcJt~(f|YLPiQy;ROU-^P5QS+lH=}DD54A@eqyf=v3X^#AHB2(BF!{lYU^-U?%OT$ts(FINwc(}*%bsGK7jxANIl=u{k zc(P2XbP3Bc>D?q$NM`Bj*$$e$AgAfy9=$G z6k;9zL@$zCOhIvBw!B7eWVT)|$vaA!0m^_Q z>fxea;pdPxDAkW=;DC~MRapp*W<1Ek`r)ubDy&4-2oD)InB*c^ zy*$sVo*|ne?|hYpXP1@3tRufBPtEn4^N!?__g#>tD*4bWxaUPgmci0-RuDnAQ^tGw zBv-QwS8-!wRZM}G=co4xO^UL2@^L7p2e>vD&p#tNIshfp|aa2&O*zz!`Np3t{4Bf--fj#M%k$ zl8H|VhO;6gat124*Po<0v)QeT3j27U9%pwdn&k)XMjpE$VI9`@_sgFgB=wi)Z!jok z4umk((W+J!IRna?RTOQd!Djkf{ZML1?(OL7H_CtpS@cIXklc1NKYPu%{iak?m0LRv z-kX{_?Hq3DsS#_}ryP@fVk&cjnTl76%OqVGzKr9=*+-_bB77iXWq@k-&8^5|!)SV+ z@^aRlsF5skkXGq>sIb7kcr$lzP_1se@ORVh4tNipBhc#p0fj*(@CMjHy;miNs{>Xb>9U;}x2f`%5+s8zIJq=L?74=H| z6|X9$T@FzIRda#_Gyl?@(Im2g!m8Fv`&U&+__1d|1Z_)J`dcOX1Wa%ba`htqs$mId z0dyiGeTA$)dhIU|4**RoN|~kWx<~@LeL$;4vd|9ytv{IpyOwnJy`}4-&J7p>Xl=`T z5o_1Qq8lD1KrTvs8o2XE4!%^m+=GCOWq~YZ|JT$15c%*+BieDQx6BFKn*+5!GQ&Eb{-JSmy^0*MDg)ISQ^y)6+ApP$l3vPl^e13jp4%UhB zpbKXFSuH-pu6;l$9;gjX za$oqZ$|Wp!A9?$ry6Q>p!lI*pnVG@t*^P`ZH9uj0t}!*Cwd?HX`;Mf3xYCwqS5vC@ z4v7WwT|PD^hjf4J`lsE8N3SCutPXyXEL8mXhL=|(;`H=L03`WNRN5x1$zZ6LC!&I! z1iP7;yqk9z*=ADHQoRokJweZKT*i3m&y>0X;LP`Jb9tWpKB4|*~S;NUoneG#!X zLVjnLFCVsUA)&~|jcm5!W`Fv4!1JO)!j6VT>)|^N0Z%MI_|z&Ei?x^pr92&p2Yh%*qC^nNmF3N4v`?$~!khtUc1m-(e@RU;F*=6Tac z_x=5IpPAp$)1ycH@Zk-uglpf@f<2*k=sj=8O)J;M%JjYq*j~0DPBU-KTwRm$Gu%c%-7NZ9-+D~l30+)>RwloE z47QpaQOjvKcp&QD^gx>LIb#%@g!|=-v=+0$*e+W8lj=+zkwX3Xa*8l2m&J;KrR9Sq z8dk-0IS(IHAIhQ^ZCPpA*=%M?gc(oL6aAYkT70uI3lSxl;Fle~OZo20_|hL4gSL^w zu4gF7crQRjs&@iJwIT@SH7#a+Np7CZ>$CMW2IOyD3D}koH^%KPEp1Or=#@JR;40c5 zg!3sd`oKw$D#FTP6hG<`zp`9N^DmXXw@7J z?5$g|n-&?))a+((nuOem&CztKwOd_UfthhMiLSYowb|9YD7d#~&iq&)|N!!{P`LG4Lu!ZD&txc76_XC(Kfx2LnH;$tRkO+hRU^Rn;b#lZ@!pwo5qql44= z=HQldviK}z&9^)tP9I>+WAR{q?;H&K-sx&9n}CEDGcz#J4tmR=R(`kH@JQV&barc< z)`iyG<-Ypt^M`{1-sRggQEtW-XfF zLc&ay!2>{F4>R&~mBj zH)o%_*X_%nr>0In`5cQKDr5&*l3>jv7CtlunQk$gliw&1*>1kIK*Hse_(X?<6u|8^ zQ*NVA(?MX<4p`H@P(V2Iwj|S?}hR#3(hTvOJe86|K9xLL-iHmbAY= zh^XLBBggB-Gc+}|k{+o_#)h5@ikZuYo0Gv{NWgj&#o?%O<*t|8y7~5DE;ha6w2WJ} zoMcD%uDX{Fr)QAJk|>bdinto?o*iX=9RF-29^3h%z}i{M$MOz>$oD66TgUbtD_@4U z6kX38nOLx#=9?;)KWEQY6zZH~hzyE7cd= zR_A*OpJMgMA3VT7D8xcY)jT>z#Oz4Axbyn$v)y1~gt~}l_;xzs)as#8j1n9yLCStA z_Zz&DeaE)F-Vb48BrBCX5A@b8W}f?9$RGo59Z8RFE1Te1o*=TONS?J{!E3R9;YH8 zdpax9cB!~~-RX_0e34nSFQ;!;Hb?@GxXpL9Y$8m;2Cv+N2DJD`<5mrt* zr3SZ!$?{pT0w)@p`AYY&49=x&zsa_ibkZaefisZKOhlAh^ZM3MO%WDMr(RU#v}{DY za%emW?6$T4*OHz?%ZP--&`(eOidv}Js3db)WtX0)rL%rkt3ZQNWm1?u3~r}=p8d#1 ztid`LKlSpNWZQ~)4l6AYLc^YD{mo7OF`1=>A{2t=kz8}d+*l$lZ|`wy(xPDbWOh74 zuXwI}1eD&Uacyt!ra~iMcG^g4Ru9v;p9OqQo9)CA4@9~fmX?-KGjC76w`(ej&fh{g zL5=+}VUKGmnl92pRB5-04QrKb6vO&@?lU}t`MoK0z=%}pYCi8Q$zmNJtuiba zH#9jcb!9hsF|_3OHWoagDNmIq&?O*1A*^<;7#ATdmUfCJP37- z+m2(SS;PqORBh9QHI{=CoL{dPABc|5N>7Y&A+ZHR^L*=8J7}_n`$0&aNxkv~r~Mi? zx#w+-JD^gCSC)s7u)81y1z)rar^VKr+}n3Zn(3C79Z(A)q&L4Vo&*u8>(4d31*~2O zBGh8kqS_WFNf&xJH_!Tfib=mc5z>zyh;()Xww<_I!oL+dmfYrkIn5b4;~st7@IgAwlXQT7n%?EEfPfef!{1 ze0)&&-joRQ%J|(7o2}dhjWwJ?f~Os|>qHCgs@1>Y69$;5u)L@LnVF8|M zK$oWa-e*%lkqY|ikbp~$*iyad6Oh*#=-2lR`cj&`+v3OgSfYXGk=o*eMLf1%vI)5O zo7HwU-V=g`Ep6_^ah%@+X~WURtw!_8d?jh6n6_OS-2JySJ&Bw7*(JDrYZX7f^BZAH z4UFh2Q~c;TPipV@(;8P@muBpP=v{PiMN=BRG>04$syjC`yE5s0^#dT;GQO zy10b?_YG(r@eK@B+OS|{I^~%r!*0OOz3hK7?bf2<#gBJN@$uZ5 z?9gYzjgplvU?`r;RaQ@rno8f(*Oyl0lY67oDXP*M88>&&tN`%OFv$~RdXWz`u4?)2 z!xT?`>zgl-(oK3g-z1%!c^maymnmu}&L6I~xDD>~l%Gt7mk=xEwUUxDZIj#Ue&VPo zv9>lTy?a724J~j9Y5jDs%bB#CJ@=n%6~gg(3V9Twtg(j@zrA_KQ3n@qf1{B*<}jwl zfK=s&dDxM4>? zPIiBNy3{N}oj8SE56^ShA52T+v|p0_v>W~1>srU}Z>#k`ipfdQXZLzyG)HmPD5*SA zLu}3XK<3~(pIV~J%KCjH;uM5GVq+>iL_{{vR?(g;x&(a;+RArMDOv|}E-FLR>p<%B+TnBP=V1ij`jQ2H#B2+E&4 zl&iGg9O=b<6wYOzl+Axex4+I)njRB5KE-bv>7Zx!eC=G$x-NFs?fe}3WZf=jcXYWP z%Z$JNz*#Pz=OBM7*xy$uwCtV3XHJfjzE!K3V0C^hg>BA7bjVOpnr!(46Cv&6vsofFJ9I)HOLSSTPh<3UeMRups|rvTs)>S%xapQ z?aAk04D@^3OY^vV(tIwDTr8(4E3`~pvj{`sSn)h!ri~KE?bA%_(-?O))5|kPr-#*k?eLX|H@=ITsTUcrm-t0}y1q+f2_WY-6>M4B-=qEL(Q{F+&Q6{B!Sa6PZzKfO^&!&PZaM=qy`^5{8AQG~ZM2 zP73RQ@|SMdoPA1~q>tonVG-8g=;_C^o)%Tv8+y+McFHGpQOif=YBTlVJ<9qjs`iTe z-K~h}dQeG41<1lS0YbZ4wF?7>clHEa!d^QqM!z1vCxDhiZsF)TG- zU~ntlE6rFy|%BJw-g5klN25FjWCvoGs3re8F_N5y@Vf1*BJ zo25R^gyHQnQz!{jVYd4>7&N2LCtT%aCyYnEn>;5+i{BVAt1RMc z(7OsulPU_VLUaSXA2glRVD9=q^+$T4nQ9a1?6s4NU%b}QMv?1gl^caugoz;`4BL;5 zP4~5x{_eLBL7z5Bn*|obOfEO1fRdx+NJo0TK1uTADGm3&d6oRGSdMT}(av{-p}ATN zPFpuiD|M-c7Hv;C|BLkX&;{a`%hEV@uDL0(Z}WjwuTBw?{{Iz1j)8^0{yX0Z>DBnOr0|) z`^99pUAc+q=W+M(Y0koCFGDeI?1-P$q-%Yz5w6ni0o zE%SRm3_EIec(bj%!8|#-k5NGjayQ3y(?zWys;AUArG#TeB6}G5Np(?X{(c|h-svUI z7}uscm$yFeKybvRTw)gdE#>%8CQs?zwlOrPuc&O)qjtq=r?Gw3?2U@cpCp_vxm;v6 zY~A6_92JW05Yct}Zdec=h3!k+i0D`L>(tIWxJ<8l1jC*^>&Q~Z_JmN^pP#FfR#?O& zx3?g5l?vWe4W}+j5k@!Scp8-yEtpa|r&ej;r&EoUk3s}TLA-;@h^4jgw6aKtJUkDZ z-r(%G(;GST`y|bhDK|{HaJ8aMTN`RR|6%@5u6*O?kA%3@M5?s%opRr+GpQ77& zxMAiQW8*$t-A(ALD|V61j*fb$K^JE_6S#R*UcWk<-NLZSPN{@`MI z)9PN)4$snweMde`S%SM}c8RoU=YyzE<8>}a`xD#dxjtpyyOg|i(>Rs26&Fo;zFXzD zPP(?V>ZM)0Q0@lZ#ZA)83Gtg;cSG>S;(f(6p|}+%ssRT44$5@cjJ!FH5PpoH=LO8SLVoMog$hy_Cexz zi8LS{X2jz+^CC%TjrTE+?xPvSn>wD=(VjX#9bjGT5!GvKG!$sZ5SP`{ z&|`TU+wjfS{X6EE^quM9%HpsXyH)ZE^d`G!ss0QaB($OW61&s`BE=K1?dNp=z_o?L-jIvfK5l&C1P#kOjV zMV~L6!AG>juyHbIMh|etS)rt5hVPvNV5NYj2Q8fJk|Hdy+rYo8R%;4hxE$hZJ)xjx@wrfA=ia=X&>arIEQhC7PlQ z5`KEKbUqs0N!J)Z$8yW3#Z({B60@q-<$S;U4wK?UQ<0Z*0=;;i(sQNpvI2&j*GwdJ z4-}*hg*7Kie=^o<>XqInN+S)dbH-%3TUlXu_*mpQmS@aKW!SK^+PGS4e%qy;8Q|&R zeHf~Xn3xu^o8GIUH9CPui@_wvuTQxJb*aVPzURs$Q~J1KoSsgT5v);ZP;88(h?hDS zBw&|d`dlQb;n_EwRt~?Iut8EnbSfl@vY(OnDJ<&WDz2ZtR$XkHwG7ZB6~EV>Y;IHf zoG863#M@{7cu&Yk?>6?!J5us0CQ&QWKT|y)%fBC`$(JY7BICSifp(V!lRaDiwyrlC zDVot2?T@;WgI#GB8SrX{@^+^u}|H?y3Hn8v)~*G}cf=Ud(2BVA2JWEgszw!)~*5)?FB7 zYb`+{VIo3RoMT$0E++1Jo%75i8&HOH?Zv!RsM#kyYTyNV>;Y*UXqu%Beo7q1+-zyB z!%PUji_;Mo2t(%I-*w?vKepd!KkvqLB;1L0jC_LOVD>GO96P`+q5o+e{Fhzyc7a0| zW<3v!=$b~CN~g~w95(l2mF^JC!=Ay;chN3&(9C`2t{t??ctlv^@iAj5Ae#D@2Jg{= zseo~Mlkr7`PK}@^yoPptms|pdmUYFGwOAS@|5{SC76n}2!2F+0jHQ?~o?(dC5mCk; zWQ>jR3|88Lq@qf6--h@lI4|6qr+0HXBz=Z0I_*X4>wAm*B9>dRZu6kT#7nv-8O<~L z-iNRB&vtc$)e9ip{){O|dtVUMZ;PsodS+$bzi`-{{Fd7%oj?}m6QaB`h_6BgN}YWk z;qsRAepgJCimS&aRu}ACE>CLlc!Y9@hW+qy!5FFfJB#DjKevz94mk3V&Vf-qqzjJJ zo^B}L+PT}NrNzf@b;PY4#fqD^$Nm|pg>#m-7tZo(9?{GGuHDO?X&c9b)!Od;O|=3f z^%|)&3|vwcS08I`5wuXpg!TJa^V}RQ+X97qa1QV9s&gVABkCTjT$CO!GzQSTj2D4) z*kg|1#kL$h{qS93G^NzeOj5aSjUkJ`fNSimZxeBk?rTS+oC_jWRFC?lp~S;Z0@5k2 zX<`1*P69r!LSKB!o4SX9WEtJ{!`J~68ulnG2aNf%RH-*1;pBPrN==FPMd}*7wgO{L z-xRHlKN-t7=o1jg8EO_TGk9PEp7oM*>?(dzH$7joWwX--U8Ll?H=CG z&yu*yMNEqFV#dcwqPLW4s65yy+-r3)%j8X13R+7sN2$*r+DPn?6<2+J^M39ychS5g z$HP=IuKknesYa^Is>rMEnkWk8z=pa~$y}O7$(^(HgSR*+809{lToD89oFs$2X$-f} zLwC&WGra0i;bGpyv*sD1C4Q3dBA@(baZ$XT^khQ5(s5(0W0=C{0WtZoPama2p8uoS z5WiaMej|yY&1dRazj@RR1j;z&-YSKIOGnVkai9XHYV zS2xgo{WvUWn-f{MWfr1YUkT0B+y|;8Ov}fn5f0BE?YA0lr@l)G^{ec3QbcSme6K8p z=TBmzp{LPuu61^@rhDO28T++qGat2Gpyv1+c8)Ig4`nRr?RU04&#Pu0FqgZ(dN-cC zT#iOt?{9_eLg12#f}zr_b$1&jb4RGdjd!i^2O((uE7ou2?RB@F|KfNj>Ah}W^M~dS zmdBG=YL6xAQoIM#OXN~deH5B)m#t$0Z@Av!!#?*-edU!Wl$5w#jev^O9%^V!<`|f4_o?^_7=XwzfpKMIN;U|_8@bH^Q(obAfz4mO=!L|(F~&0fLA1&Em9s*- z+bnk|GRbNRlQkKgXK?UFFVT2BkG~jE2an_z!AEo90t-m~f^c3@F^6yRS_KVm-iH5X zX*EIl01M`x`7lQBwO|*RxL4|`MGtT-1v%fo5h-)wy4lI?2DeRNKNo7x2;-LOSW52y^ocNa)q9I z!dcucATU+Yae!H5ZIi!nJO+wpVfIF9(fe8@95FTqA_l4iwgBM8wufKATN%eKRZ*F} zEp}VZFn(w_ZU~j!4L*h9HPpHVUhZk|wB^x~9~XB8_`?@Tizdr&#e_)aN2ocuiypRd zr7*>X2D{V2m-xy$>5WN+el%e@*_9vvxmxs|$!mG%jjZ0;f>*&h^0z>$RVfpNBRQSf z76*vQa|>Qf)VOda*~et7`^QSzCfCd z36FXjGK_A0cIAvPl?5>pxk)$LX@CuZ0yZ>BsOC-}pM~mLf$04jilBJ*SR@}{UidX` z#~L(%A^QRj3=qPBAmZhnm^sA$Rcp$0asCHCuX^3;^lAV{zT-+qQb{7ms`c>IH25@- zfS9&WTL@5)>>v%sJ3^9?l7k49Cum0l4479RqfBN2+r=0D>;XiT0d$WW!QoQI;RIF=#6^2pDa^0Jk z1A3HDLsZ&ITww{5{&le3P!Grsi1hj6HTu1^kP$fAo`GWoYv+Hh`GGt*$nFbxw5$F7 z`U9c{-OM^o!}h-ru!t8%%&_Nb3cR3(_ww4OiHD-z;>!*l34^T0$MLR*qg%!=6AcGH z8(CT3gBi-wqP{Ryn?% zN1iC6E7A^(e90S6GrHh8W7t)t8~O_9^X1eM03?)HGQa-$^b+)&{>)pvE;HyVt2t2t zcYH@{%&pPZ=Uc_{qOyi&O1LbIN}>j{JeAYkQ1nplzK0+>^4XGJt?^Hs6Q1&esoH>p zhk>g)@q_nxj=hgxq5j*7>`A`8^KglyYfG=J?i&LL;dGBm|5Px>MZTlWUlT&U6-f*l${z)OL z!Pp0~fGz$XEj4$lF?oo41zPIWWlm8Wp^g$_3tPv{IIkJ10)OZwwiAvpXZnCs6sX-RvB_@(W}W~w z6bsc4j((%^+R_|Ln9N0Y?TIEjN)&AamKW87+>W+VpFtgu%Oi=seCunYmOuK5vzzNU zj=W{UFAvv%8X5?+YWji!dILgY5Te!NCUFY)cCegpF%ed{qme#iphQD95v9iwow&%n z_!t))0`G|X6Rc{!)Q13{pp0;6XFB_(TlvXJ@Ufex3kuZUmT{wcWN=bGRHAKfe`(UZ zJ-@Qd)(dKD)0KC!x$qi8-H#+wgxcAjvjnvo2lw>vDLe`gcO2=mJo+cR6icMFH1EO151^`7c}d_l2Q$J6UDu#;q(gGM$1fX zsUS;MoVYqlw^qu+x8mewA;X&r1i5CV`AcOTcg2e9ijNoefw}5cpE`5?7}?YV`5zA% z(za3jsCf9KV$9oe1bmXUg@oy^gVsUiI{U`QovcV|7$_ z4}VQ=>KpZ?*#f{HvP=rmjp9k9P`R}0s=jg8)U5`lGjivJ$d4*DeXpDn_N&~E&NoG? z(N%7y>|&#_uZ>Ie6xx&s!g4ZhE9c;$6Q?K$gqDkQ5*BtCd&s?keVg3)LT!n+YSkov zwU#tVCsdfG;FF(bW3J6=f9m7%4B!o|^LDL$xvB*;Dbc6iv6kNDnFF8vBXhB9$Ujni z)TI|L?-(5zh_yEv@o`73I<9)`^ZV}q2VD7Wbs^7@eAU_3HMeso0MkO*oF<2;+9s!I z;chX3KaT>3#MgojvKce;_R4L2L3FR!oOOPE%1wkMv&<7jmj@fJB=Y5SljKY?2;p1@Y!Cy{GyviAlC=_m5fPlQlg1(Zf%dbB*WGDzdF zy}bSqSiI01y)I(Rfs5+ze4LR@$3Bw5Vv~=x?T=4>{P?j@mL89uP9vot&tvml<)fU9 zoB|i~(Kni`3}oyQLYng#D@={rYxa5R3NY=NWX=nIxin}nFUE>=;qm>L&n&%58({{m z%S7lqc!a~b>!nIWt(`4Gnp4JrSUVA9;ZwG#7HB?Iyj@(~Hy5Q^W48U6LyBzTj!>M= z^JB4N<`&&cM>&kT>H)DEH0wi1u07XHMas zvA5V|`ED`s7!5tMM%hP=+W?siLfX?+5heI4tg`mo^Q2-vvnriCY@BSwm5!9;Z*uOH z3R%D=Nw(Nyy{r?AZgjEvcA9{T3Qzxnc9Yql5KR&z^~rR4lT?{$SK3O339VS*WW`JU z!aH@pX)r&m+Myid{)KmRPkEV0zJz>*>BJz_dznwfbk-SSSPyuLxtSv8w`8z>O z(BpIAjD1zZO_T%Eaq5x=BbGV@Y{LcTQxwOnli=v={&ZuhWT14>eJA66Kqwy7Xph#_ zH8G=hdNXXpV=mcOzoj2&YZ)vUd?;_lK!ZD5Ocv@-Ype524eQ4FHdCr{-SLPVh0j{x z3ww-BbqtafBKj?brZBSd*#*kNBhJ5Nlo%UzVK(GT%Jfhk5vBprhZP5gAy?Au2o=li zt_e%`v*5(yUvh1TZc?O+qLaOc`<#b#N|j^yvEWx!GCP9>#*QZ5qg~qEfYu2dsVyhC zRM}|BU*sGef%#Be%-JlS?Y9K-OY{hVq>+QO&LpP6{YCe$WVaA>1mN*+NpIu%1<>E0 zzYJCY+-=R~1q2={lP9s`UR|0BU017>ibHByc%#W^)H<`?iT zH@F7il*Smg0gZ#EKrdLIQU0Gu@E9;BT130{W|_?TUrDve!pr{wS27IjI6L!gAE*cq z%wNeHX`&;t>&M@xNEUWmDhfWzPNuz{YUt%U-ji-U^5b~V!PKOn_G24(M#`}i;QEd;^~ z#Fy<5=C^;#_wI1)((X+%|24%Q!2TDY09M}f*lIvkwP@A2!bC_FK)9$)Vgwoy5X_DD zAM|s=&&Zz@|3OBG2ZYnhX$Gp}LX=6-u<;$!9uI~%1-G<%*Pm=z9HqTXXBw$lOVKxp z#)h{Jy1GQG{x=wmR@ZE-S-~TG@;SEGDWAGNkqK||i`3b5|B@9hPs$|lhF46Rf-NcZ zu8EK~EPfgor;NxiVP*SAyM$=B-rrjS&Dr5X8R9>qiwdBONO=T;~uq7sVZ|E zBj*_F7xjSJ@v&np+BYFsNhlVwYvssZ>N3x`@=}$e$pma4gk%G%+ff2y!^8Ec4JU?E zb#%i^e5r07jCX%B&eOG2{lO? z*uS6){qvF_fo4(gC*J&T?Y(tS)?d3XEJ!2WUD7EECa&zv)7w!Www_fx(RQwUx6Dmok}o+eXEa%pIi71+K!;ZZnd2+R8oX7kS z%lrP|Gd?pgdBh=`37~LH0jB12;Jwc6#pH?~6cKa3wu*zn>L60OS@K*%%{N%qsJ;CP z?qw@}9}kS)qeNA;j}FF>Ma!+=L{Lq&r|-m8IB%rC+}qrjrZHu4LfP9(9E=X6t6N$K z{Ma{Yh8NgS%+Sy5nm8(pgzUpFswltk@jO@BQ zJ8fuaC?FP~Ag$YH%$U%F3jWO*RfrCN8LDW&>7%XAMD`EyermKePM`>gwI#o-$OLRz0*Ui$CnB>RFkIed!W{T7K|Wvatq@b`rh9BEZNZss^`=D zrl|!M441VDYcEfy*1eJj%(+D`m$_cFsrX8TL?PS7E{%7!!t9fPk<=zFvp+kMCI68{ z7zc2Yq&UE%`In_pe|Lfz8?0TTy@?sSN~Dr8{Bxm&{mG1zx#fK2#gWo}Rpu%py=e;y z%0v;pr#D&&2gg3K$8p|aajYtmUQHM9$_$1pOpEkAPI{ZN@`{pxz`MCwduh654qzQ3 zFoRk#sE#Iof^Gl|4c`;LVmjIBt%!rJj=5Alb}GI1FteR|2VC|)juU@_*U26NlYxzc zX{bDQHkK_vXabW{qMt?CkH;=PpirXWZrQl+u!Ao3`MwY#Mld zx9+5SiBZ;MilKa+a3&wCJ~lp7ZCl+`zg>LK;#TIr4-8NJ;9CEO8HqiqE-4Mwq`Z6U z;Q$I%L@%@0+uC6sg2d}>kFS~^!oAv>4YKkFkC@#7IpnPY;*YhVqN5;U#UhNNE zyj+4JiPKc?RDwQ*OwBvji$f-=*W4LJbVB&0sK&XGm}fUo)QV@xJ;ZvRdjV>YIjs!# zub9{Q01g8;{9}QF@F^$eB*WnN*tcTV9<7)@IkujR*I!IfC5gb`UY?feya)E?_fHrk zOw^uI-A0K3ir|m!&n0@7eZ;*QAwA&RYpBA+Hh|5L&7gkv_~}NddsA7HwrOW?4FeEF z9S(ak@IsXD0zcs|!haDL0+9PRZ~oCHz%N3~9vd4QVeVni*|dS+zX!yFm;z(!eMFQK zabh|ulboqu@3qNQd#p~Syj4?sqocf@Kt?x*^Xz6jx9x~=*glU-VEUgPq6+qMg^!%7 zO@H^|aI@ri8=V)eQ5MKkRnZf0qqJeoa;}yEuMOFw*RC#i*I!BxydJgAeVwb-fAhA9 zE}E%ghEDL| zj`==0k0bX*efT{$9+WK-U0GRKZ8GI~?p^F~yrwx?TFOK~Kro8KVQX?De6lqrDlcCH z)HiQ*0v=h^SC^GpCbQd+l98=USlijjV+$!ObI2E~0JY=;)fH_*Qd1X*+-@vayD`Sb zB2>2)7sKfBnps3yxmic4JTNi^>y3=Lzqk_Y!!{PDzWwwDkQ~+BkFFVre4|5R5NvyT%Pn3_;@5JD+CqF?=J=89Re=^E{`@xHs|UW znw<0Ml*&avTklNHw~$QrNlzZEttHZSm$(}m%Xg|)(CPU!z+RqQMJi*}ycxH;>pweB znzcei;=m^$M?S;;VX5)eW81idk+IRaeD8-Yc`WCfOMd*@mE+JEWz*Dft8eID)S`im zjb&=?Hw&}(cN1rBLP_{`A9opzI}&1JRFw7_ob!i9ZCEB8%nvbNt_<+>t^<~3uZv;%c}+mZCQ$BPoV zT;)5)x3tY}w7^3uRzvFi@N=S1I|pzt?G-&0#*l~V4ox6@EjaoVrR z=u1L;cNR0VFy|y+ZKufh5>QX(wdWRWj2dQ1Gq3$r5r3?g_IdF2GS#eTho&Z47K3iV zC4!R)@$DCZmnb>pv}0v5H*cP6lK>`@B4EfXjysI2P{U?%fI~q+K_d~Of35;byJ@!h z%H~Pw0(Gd5&{Qk*5X6*AKk-!0)mnYFKU~(Lrqhtr4YNJpo9l^XOpSX3RAL8`KJi+r zHab>0UmhLZ`frj71mFYrg1S5Df8Z+>sWk#OaDnp(;yj2&+eyt)sT^s zXKvuZ^UI#(df?F#^hB}GGIK>as;DN|46BoE8I7zS5m(aOs7$Z5;f!ru!FCF{D0>j0 zX*^qrGq+Zq!fH2xU?}FuptqIdIoB7*Q=g~MxYpa4%^&6ZFE4ghzH&TG&+)wVR9ACW z%(u#u!&3$mie8e{i|e)DB^T0FQTJ-LJ=svm{XmkHUiFsJ9?Bm2hi(7u)wgXe(*PEw zQJBjxecGN9XPZ^ou_aln*#5?wE?{{*v3pXua#irh3{ktX)l>O;xogbdb!}G1K2xN4 zGPTh&7$W|<5RFO-9JzXTF##v8#JjK{mdoqwSfEbvS9h?uzErn6>ONQ+M8hu}BKgm1 za&mIW-UYcU%~a@z%18@jIP3r!B2r)^I3y$_FlgnHxZRrK<8hwZb$L+mgO?*WMX|E7 zQfkkY0Y%3lYlNd16w4u=eoCe-qQ>N5TN_9vD*j}V)tkb3ooh~{hPI_{(qV@Rx}kDrOI}U@|LQx> zk1+O!;QJMhCl_|3xp*llZAN3Bfn*=|)atzXrLC+kq(Y3Rj>c9xyJndjj!ycM!`&N; z)jI-&7NwM=>8>u$b}J>4r>CdJ*qFDJn{IH}*j}jH(B?@fksF1S09Q|jDwK7JE**77 zqQ&{ReVZ=!J2so&lf7h@ve0dZB#X=K4y!IO^E)p^(sZ0U)sU*Mxt>okbK2Xl51rvw zy9bk{cokN!5grH^%52B%ws`oYgt9Z`E9v>&&^4Rgynj{Jn=Tfu2*8?!1&rn>AfyIZ zaO@<+G-W^ydz+w6H@j`Pt+dL=T$8zX!*O{aQw^oIy%zWVa!ir6my9;82!XxO=d) z{1GTcViunQLHI$ z3jg3$tlHM({H9#fEB5nx_x41e)q4N#;^Ov73^Dn$&c6MAc?&B+iyM~bf>mUXV{r8qgQ(|`OpxgM4Z7&Z^+Oc@+ley{fH!=cXAm*I#G1a|H5ub_S4 z9-fRy0&ZH)6Yqym>ZbqKr8Ym{QTx(UD^F0J<;u6UzC<9W3Pc_n3JS?|Rr_W?09%00 z!=pgOTr8M3n{py=9Z!TtKTfLJ0$PR5+?&xF8WEpL&i#p(O;1k`JZX1(J48GoA>kyX zUwaVFOJtWU{ehHFBJTN8&8Oa^J9_Y#bf9qTXnw;!LQY4G{K;>=hM5#Mtaxl@Kpjyj zn3otul95=jI?UjbTD8aPe)lBfvK8WqbMRPKD)n+-RNm|myWH+5#!n(-FGrLqKkE-3 zK7wcGh_$s0H_L8cNn{H(nf0F;;Ng)E!3VDHVQ0yAT%C5nQ5DV99(TzWXgJ_WX2UgU zD%u`qsP4!OClo1%=BvB4Ex6s+YI;e>GaJmJ4;(*6Lm$6!CzK442#OmA;kW;1( zRfYe$)aer{v|N!Vlk|{Cf+;S=vp$55q105Trq4Zu*Xld<$y-o@{D8$gBJMg_RbU-~ z=|fkCzkRfN8@sNbqK%diT8~s6Pa@bz(E<%jUr8iQj_!6cf)p12fR1}ERg+nbm@14unUBn77_l)~-CP=$e(Z>)udpI@X> zD^)m~`+*Gm_89_#Y>gDQXU+4lA=tM^M~*wIW6ocn@V9j;b&use{dGMXMZI}h8Iz!v zDT}h&l%vwNsPYHqQ)n6ty;vlIR?+;Jo^N{X0T?k0)rniU*w28s;rY*Eik)H^#x^HE z$mr%GQOkbeg?!B}V%p)om5`gtDH!5AS05OS(y!Cj=rpPLxh}dD+0cqsq1k)8V+!l_ zUg3O_qXR9BZHFD#ek)&V$J0Trp6CY1S;WbCEvIB0n}8Z>wMu~x4ajjX7UkS|W!vF- z`T?&pd+@UJ8@`wKw$*N;U|Y=_s#gz3a_&Ir|0N{x&o@&T;9;bxTrQrRG>44??fq!+ zJ7>Ey{x>95o@~T2@wK&YWN=7nMJ_u-iTqHW)qsJ4A!un=2@4#-@~eBBiuZazYi|x` zuZo_YoWP+|xhENy%_#9>3FdkF_&|Cq+S`ALIvz>j;o*U?Aa$!$nya%J+Ug1?vwtsk zf293F9DLK`Nfyj#)TemlK*n&aUftZyCKDVrDKwbUyW_P@Jly53a`{j~;mfCM1N(1m zXv|Q0nnYWdr0`C+#wctvsg1OlYqf3zvL%jw444}+m=vP&E_Jqlm6f95B~6Wt92hHr zJ4BV8cxHb$J3X&v(DN`)A8QQ;n7q z@BP{+wOY7UID}`MZ%-_A6tWz6tnTsdh*Dg`BuZiuCZj4W3s?N@Npkgmxy}BNQZ8aP zoMfDNh!3#+^x*YkixdL!#4ssvNq%GrDPsHA7wLjus3}JGV;R+vj|lanK8d_5gldGC z^AXp98Pe3%^-hjpF^`&kj9AfVPEpIk^DYqs)szoY9`)2?`gwK zL_D8`|6FFGovU&nmAhv`z1jpPOLZhiJUl+`ZgqzFfv#WG`w|!4x?Ekm)XOSKUG0haG#>ACERIwgm=D2WD(X zM-D+KmK*Kt5}e&ZpoI+-*sCGuh-$cQuAfhAIPBJoL->G$vVWH{!wJzT&(8L$Hz&5J z(dqiu<*W@_DmRndDtFWUfJACts%@M@iD<*_3Cb}FBm~@GZJ<@v&{&qyFn-q6ga1oK z9=7dI}j4!Yt;~j=JXS`3O(~8YuUf_o4muRy20U9pFgCMGVz2ogaR- z8)_rl*j46lj15guuQHU*Wri5^W7>XeHe1{16nk@by+bC*FYGI!5!*IjbkRu80uA0f zJdTNie%+sfu)>l6Bq^P}?v0NaE1+{ms-h_67(*3v$^J*rlo#td&0c@_fVM7~$;InVJj?AFGFqsJR>PFAq$)rgbwui6E&BB`R-LKl z^7cxV%h~?2E4 z0-34P0qzakg#ZkH!TXal(^paE(GAuUuxRtw*GMI**Uc{15_^*#R=G<7Qw}%wCwgJ3 z2YVc~E*v3pe7pjE<9vQb`aQmq*D#Eq(#X)1Yre4w`r~HQVTg>(=$hyTZCpy~#$oRy zy)GB?sgh25D-$DZh6cpRBWOeoKCsuZZ>UJ=!pdrM0frwhgux3@|7XX*3DT&r#_iRq ze*z5O)WzfgpM_QwQY%UDb9O9}BN7$NvhYHasdB0CxUVm?{M}w_wt7E>MpS8Xb~spU z0cg!ALEq*BcOYQhCcolx9dJukDLzck%hn7oU!mIMT>ILw-gY-%7VWLGOyzPXZaBum2&KojMyCZXx4X$4aV#YKug{KO zvxfu+hvYITAFj9_T%Thh5z+xS;e5nZ25s|j!9U(Ot$h1bq@3P;)t3_dzGPYQ{q$gHP$;d&nGE;YnR+v8gNfH z(laQu{CZCg6b75`Pb89=5ENjb?~mV`IXPv?R$k?;3C{;i1^^CB1?pg{JXaYJxEAv^ z99kIz7%yplUOp+4m?dRCl+e1a616UsE2_;WOW}2R@$AjyVfN@FqE?xNM8|r8=b^{z z1KR4Cty2Y)8Zo0hmWV7`3vIdNzI#GOR%53nDz%QW9SzbWuP;97#q5Xs+Y_Oi+LpgKT-?`Mdsm zNdfUZAyMOq2E6pBf%fM`!oohn2G7Gjf?q_-^th${O#0AG1nu+?TcZPOZ|aPmoc>ho z*G2jTRh82aW7TW3z$`B#CjckkAlvbEOaurQm8quso9HeYs1Wgmir=);J3lF=+f>`) zUtc;MK~eO0h~t4k2=g;P{=+F=7%DgqkLL7rB&uWb+spPri!FbYRzq5+vsu2XKr9#8 zXLjrTc%wLMd;B--pA19fuCAo-E>;X~){fpF5kUo@aan*~1kuE3>%79q?uk_oH*c+k z1FwwBb8jPkbm+7XAs3~-b{=rPvniY{4GZ@CZ|5a%RprKzM`@KA7H&|g<3 ztQgnb?dE5!6^GP24_qTUv5EmXK*%H9!^8J_<8Amq9|39M3RN5cFCVonmaAQ==^xYAYDQx3e`^s4Gn+VFl0&QJsmSMI}MGJP4eV-7+F^HGqd3z z&=b-3xBC(XxfV&jOh{^<9u5LuOB6mjjM|I~9H=T>;UZkI|#=;%+n z6dfdbv2kA!lbgAd>Bjs{8%XuETX|Hy?}CuEa06pQ2Nuo0qu(n3%D$JC z8%TslHr(3e!qw8EnUiDL>5<_)La|Rr=&>Xy^rI(eWS57$PVGlp zvpG2TC|<4g{u!6+y@5nKwX>a(1hxfCWaJDULKh}xGyOm*L#oE-{Ep&hbxh?5q zXdodAi1E2z(5lXTcR1=LU|Iwj7CBueJv3S+as+B9gn^lHV>IKQa&xS2!hgSE`bcUa0;bY*5m^P`XJt4N4%!vYXb zxEIGe#OqG$_i8d`1J?CZMc+s*4@Za^aEuvj)g^2c`HDUF{W@0Q%BTiGJ&Mn9 zcCpyvcl6^0A$#SKA5wZUN4@FXRa>YBugk3K4YuuVof}XV7M~z|W2o)6{S#&LtsGDg z-I>W5fr!CGJF+>gduwdwly6UC2ewR zo=(_WJ?37kn6v~}HQMRDkPdPHZZd_IDWy$A@F}b9+rbwzp+w=LHZ-emhF(4=Zl9dS zCTMax*c)4w4~}8IGCy-{g2d`EZh3?6FHV-{M{d`A z6RXEe3Z9i50S7eqRoAJn3cmVzqzoTiD()MMaYOBRPpx#vE(kwMk{K&ld{p_M12zE3M}0Aj75_o#NpzuE2#D#cfKboo1?F(AJs&>7oMCye;=g<6dvw+}nDdHR_X+t25wa0BcQ^ zYNo(sy)AiLtYl=}D0Md5DmB4g#DL7VM{(V5Sac>IuJViFQ- zgoH>3?6y0?pHSt1G`NC7-`bHT>TF&Znkxk3+U_s7VJ*oQU+_djLb}-4?WgfZYZitO zi1Nal&e7al@W@?WK-lixw1p0Sk9^=2!CnM8z8%6E7WTPNrA)qw@;tWrEvBT z6UD+wV$iMy`}-HGxzO{^WeR#gBiSCE>|oANAeS!tvB{?Yd)vkVx5%r@NFBp1L ztOxUY+@_MoFq5bMU#I`Db5=ceO!TMgwnCH*vOQ36&IkU-TL( zSZZ`=XNEM^0%`G**^q6bq2y6R;XBu-jWYAoY4d=TPK^DH{=XxfDC~Bv{#a%P$4=t^X6=yaZygHc*?e>9RPhcx?UHRsdCGjf0Yq_;ojlye5d3&A5 z&-F~qJJp|VqZ5Ws;j}>Bfm4sf-;rckHvV(S_mm!TY27wsL86}sR;XYo>pOEs`! z{}Hv72;6cQ{v_<|FALMTLhX%A1rZEW0h~N)qzL=O$7N@)vuEUZLc)IJbxmP<$LVtQ zfs69c@bVt6JL)?^D3JHru2|LSDeDV+%KQyzigF;OTdPX7%e84P^U#1~erTT7$V56{ zv+x@sfA&&Il0fawIv`i;YH$2Hvd}|5Lp@*o>`TEAYokdEQ3Zt`TVs7dnm9hk(~UAa zbCXFtc=#n_7zjqoj{%t^dzySXaFR@g^eU4U{Yj31ZQ%)tG#_20w0m$$pr?DPTGBo6 zMs`GTHu{C^RJqk(yKoTS133HG+}NI-wMJvS#lP}NxH~A~F4R9#?qDh!Fy~sC>l&tV zDzt%2=gF$28I3v$_iwI$7XPhGF80i62C0Ef@-DhYO6{^*tRVIYt5!OnHyfQ)yOcA} zWTiQafDrFgY>6)zAQBBUU@H2GH@934#=jvvH9dAlzvJZ7 zv9seU54D#uL7--EkfVl&f52m#M-P;7=RNqgH+Qb(rC4QTTcI~b@FD~5hJGo4nsxNR z39}~7Fpkyl(G8|i(kJ`vyut7eMaQj&gZ>BU#s_V%t+hQrTpf=#Gc!ZsTmyN*>;!lC zyav+MOpqaGr)7a;0+dA3DA{)tH)L&O9TsGhOPFq84q6!CK{gqya2O%MZ`M}!M%I;5 zFQVf!8NgS&r$+Nu{9k*Q63Z4DIc*Npwu9rm%&7|xPkG($1K;#gKP8$7QT&HFTI4sw zQ8bFto8tjAY=b=&5|fnSo=F8F54JP_d98)$TQ_%3*?{Gz**Og;Jf@s<+-34&rLjuM zbd^ajHtP*dx^xYmV?4GSlxsq@aM)F4CEONq)B8K;CvEO-L>>5HZpmPwFBdixzaTaD8OLLbIjNxU-L%RY-WDj*d1 z`zLG*Ld1r_Co<=S*v$q3OpU$G<=7m7?L>lH&#TnUzF@Z0R0lQSu8}sab_2c&zGS{} zZeVGEtNiVc6dohA=NxwS~Q=dybDfvahK~C0y3~fq%8x;APN<1o2E!JeDLPO}wd8trV{y z#x|x#2=+q0_#9oXr$S|m!m~2iou4sv+H8_SFnDg{D~@QccIWu_l)NIc6ww?@~M(;|(_u@{yz|)6eM{>iL zchp7Fv)VDN8*jGQz%R&h&JYA9-$u43OO(wdNmYvO&Rms`HybT|mZ}ke z)%@x<8&lnI^3jxFw`t-^tH0E^ujeHa50@_&9*y(s@b8$f>6jQb=1=+Mvn(N|no_RS zRvPB8akirNyEo9y3DkLw3!lui7e^C3~N zQZPiSltvb13U=}a!|mRgvW?DJEG$u79o@mV;}z=symiE3Vux^Nm}XuWO4_FqSxG^T zk)ubEAf%EX>BMOTq(c7^gOiuRyjMi@%T!a?W+LM0M3r79 z+;)kn3^Rz^WHN}~V;e>Cc*KEGSVMaG8=H{KYx4f z(0^P99Nw&3H7)EPUp6(lH(9yPCf+UQ08bu$mopOyIWO8d#Bliaiyj$#8Z@#}Nx_92T zu~V(NI+tf`GCWj>tiN}(!*;kOQsuU_8?p)Xy>p_vS>7DkPvR=w{mN3K{?e84y19n? z?W-%$CT+7m*mvwOTjWHL%DVk|3sSy8Q+ci!R$(%x@;}%o|VST!Qc*V5}L4<7~_fApdk91&cr9M%NH-64Arh zZ0cZtvg>93o;l}k@U!c_beq1f`o$gmsfaze>0t?D%02DzcCW3iv51iS=%!=cubzAEeB@Bz-|RsYY>*4oih`8Uczf4W_yKCW)mrk1 z$yaYj`{A8nPVFR`CWNIKQk)wP)ECBNW!T6kIU z4GE@Zoi4%Zs(lkyzz%>2Kd@^40hK?imVxsg(0CThZKG38Sps!$$`n*Nwwe z9OLXNd{G)UVcTH)aYM%*yvTC-+PsnbPE|knsSFIVfjo%GSiaZ(cUPbf5Unre)1&Rw ziCiS;PPb1#t1Z;)n!|ipawr`I%j-DEDL>F8d4F?=R)N)vm|DTDDP~{1b5j2qs~Gz> zd#nit*`IvzJgy_667d%&fr!mL0%O!)ZF?$eGs@xDpACfE@8p@k#W3@$i2(|zSTAxT z_P#d%_RVd2lDi`Kep~qrucy^%IHcM6=B4_b*g{YfY&~v|2UgJ+1Kv4Ra0qr3gOw5k z%GejNzj+lzT=(^4b0l`Q;rWf(hEh?Ccgd!(J%e%QEk~;lFCl!H>1lES^qo;!G+Ufc z?dh3bZ%Wzn8OFd}PsQoP3ksKJ`;(1(LIg6##=YSy`v**^0MwlwgnJMKz;=01qro)q zUDj_mJ1rhQ?O~fGbH4Smme zyF46NVtOiWd@3*tR3JtLm@5$is7CR-+YES>Hx{d_Y${FX%1+0ICkK0Nf_Lj(>vwBb zmn!|TFfxK5rhpyL!Ne8*f?0FI2Ukp6)2mtZjFEUxTylrlumg2pWOz2Aagx6na0k5uYoQ}c zGJM?BpPcxy)cZMaW;hrqGH>b^Oqlf?%qG>1;s-Y*RAhCJ~gJa#-~Z=O5b4kGXONOo6tJ3 zKSc__%yqlU^3KP1m#J!FZ0oZJFJ}>>B^gyp{s<5n;z4x}&gqBgNkQ;JDLXF2w%K)S zi~Poshch4mVoGWX9>X+^2hh*NAO12LfT1RU5t`n^vKa+bbY5sRn4x|ZT)Yb+~ zPYOohxmnSziQxa4BZVpK3gN&1`>%-Zets~&DEi-U(rAB@xM|J5XT!gu`~P-HdyBLFTlv({hlwet z7Ve)3I9l9hL7(f00*tcZ0I=J7=p+=NTP5W@lF2xFrt6x1Dq2t?xLWrlMcmS3e)6XW zv;$@p;Ukp>c)bK@nBm#)50o|oM>iBpF18G1| zp!Hfj2537bU=RcRj_)mAFoUc9?<&&MS_oqU0>D~nB%T7{(pja zY0Z6yzi8|+4j4n*k*7rnEcy1}!iP#*-$Nn{g^xh*_j+?+WCV!kn`1l`W$$_?DZ#*3 zAS2>m8tM0klmyKoo_@;^VFkcYWrEg6DoFt5CZ2CKZY#1F3ujNg!br{xSfhmKaWzH` zTg3^#EwBHiX&CCYrT>%N_S*tU69bo@vpVX(<4Vr_J>MAT~dw8|rIwqsP)NggP)%k3>a(L{Uh3A*6;Qqg_yf7*&O{q$kWqZBk; zBJ95vwy%G-c?1hbKEQ%5C21 z;s!}Q88*n(S46g%9r$z6<6skO=_OM>jlse{u#d*XM$qFzEI#H2f5!0&9|vdC0&?Up zVx!~%2d2l#7D(6gPycCxfCeOdBQ*1fozfZr{5uRttpC$71k8y)07NoqLm+JNkJO3+ zd}Z4Gsm(_$>p_SDcu_xyP5%f|U?h(tfW=lhIg%f->>wF1L@0ii=|7zTTcrlDScCp& zt4Bm~eDLhUy($qNebx;q=;-qu>&Ju(1qjFaF|7JA;T!-KJ4#9J|4RVm4HRGqLBwI! zzl%Vo0u;I2e8tF{M=Z-pN*s6E#WM}{=(AP8KkWYBK|GI;f1}=phXN@6(5oEod6g3V zw#qRuYe2e&wVatuIy+A^9pWi4mD>LDn=Z5j%qWG+N8Au;K2BB(KkRP@nnLRHlozz~ zWgGraJoexLO?TiegISD2lRkeNSP%YtZ5kQw8mu4MUBDsoiJ49&t4B@$ORMnTI#GX_ zvFfG1^o*(8dxFA0fy00A1)S(7{c?;>Vn7#fbLXeS=6=EeaMNJ)blK?}0T(Py6x`KD zBvym|m$R*eejxP?GyU1WXo4C5x@O;%{xJPdP}2igqvyr>7hBK_=yoom>W`KB6Z=Yl zwo&qC4tlH#<^X@Oj@%dss{DmVCEx;8!RTT?0s=%G;M>@Uj@Lc<8nOZ4?-`?XGd*r= z4LEY!F@-jd07yItP?hHplbU&6J+8+df+qV^6^Km zyE`ZlV5C4v-+$3n%D`teIz^A-6i+-b0dDvo0{(v`ASnDnp-Igc|9e#HqCTjv|3*K> z&XrMD&FP(vwgmj%aSsJ>;Uc-fsu&>dKrD&rF@13G+g@#20$i$JrfM)_o%nAN-32&2 zJz!JhK$Ic_)TQTF{q`-uq|%Jd%=%Li2P#vt=d<+D7>Bthzd}ni#6YxYG0gOjrTQR$ zwczbT70U($?H++n1_%@vd?lIr;~V}I7=U>c;KBvu8pGn}O^`ir}8|~TUM#x_Q z-~k6H5scS5%75ZVfKW<%Fa`e~B3&JYBpxBx#Ufw*go(5BUinX-yjZob^$$9~LqsSQ zu}-Z#1iCd%4~W&t~EyV_j*>gpTT9K~;l{2&HgDf}>1&xe@gZv~_D z>_2$xsxO-aiQd zNfnGa>N1`ICY8q-M2Oi8*UA2jMB`0&lCCJj^{#jztEqu`)6gH_2!Y=tX=}ZE#^fnq R@C5iLEFi&O%&Xz~zW_6N2Au!^ literal 0 HcmV?d00001 From 878caaebdf3d72734b5906500d37c7c7020ca786 Mon Sep 17 00:00:00 2001 From: alonamid Date: Fri, 27 Sep 2019 23:16:19 -0700 Subject: [PATCH 37/39] Update docs/Advanced-Usage/Chip-Communication.rst --- docs/Advanced-Usage/Chip-Communication.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Advanced-Usage/Chip-Communication.rst b/docs/Advanced-Usage/Chip-Communication.rst index 60fe22ad..a9b72faf 100644 --- a/docs/Advanced-Usage/Chip-Communication.rst +++ b/docs/Advanced-Usage/Chip-Communication.rst @@ -60,7 +60,7 @@ mechanism to communicate with the DUT in simulation. In the case of a chip tapeout bringup, TSI commands can be sent over a custom communication medium to communicate with the chip. For example, some Berkeley tapeouts have a FPGA with a RISC-V soft-core that runs FESVR. The FESVR on the soft-core sends TSI commands -to a TSI to TileLink converter living on the FPGA (i.e. ``SerialAdapter``). Then this converter +to a TSI-to-TileLink converter living on the FPGA (i.e. ``SerialAdapter``). Then this converter sends the converted TileLink commands over a serial link to the chip. The following image shows this flow: .. image:: ../_static/images/chip-bringup.png From 42ca66ce07a3f6e3b22b7f0269293db067416703 Mon Sep 17 00:00:00 2001 From: alonamid Date: Fri, 27 Sep 2019 23:16:30 -0700 Subject: [PATCH 38/39] Update docs/Advanced-Usage/Chip-Communication.rst --- docs/Advanced-Usage/Chip-Communication.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Advanced-Usage/Chip-Communication.rst b/docs/Advanced-Usage/Chip-Communication.rst index a9b72faf..6af7213b 100644 --- a/docs/Advanced-Usage/Chip-Communication.rst +++ b/docs/Advanced-Usage/Chip-Communication.rst @@ -153,7 +153,7 @@ After creating the config, call the ``make`` command like the following to build make CONFIG=jtagRocketConfig TOP=TopWithDTM MODEL=TestHarnessWithDTM -In this example, this will use the config that you previously specified, as well as set +In this example, the simulation will use the config that you previously specified, as well as set the other parameters that are needed to satisfy the build system. After that point, you should have a JTAG enabled simulator that you can attach to using OpenOCD and GDB! From cad0b1f45c35c2009ad537fd9a43fddb9ec004ce Mon Sep 17 00:00:00 2001 From: alonamid Date: Sat, 28 Sep 2019 00:22:53 -0700 Subject: [PATCH 39/39] Update docs/Advanced-Usage/Chip-Communication.rst --- docs/Advanced-Usage/Chip-Communication.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/Advanced-Usage/Chip-Communication.rst b/docs/Advanced-Usage/Chip-Communication.rst index 6af7213b..902a32a3 100644 --- a/docs/Advanced-Usage/Chip-Communication.rst +++ b/docs/Advanced-Usage/Chip-Communication.rst @@ -99,6 +99,8 @@ reminder, to run a software RTL simulation, run: make CONFIG=LargeBoomConfig run-asm-tests +FireSim FPGA-accelerated simulations use TSI by default as well. + If you would like to build and simulate a Chipyard configuration with a DTM configured for DMI communication, then you must create a top-level system with the DTM (``TopWithDTM``), a test-harness to connect to the DTM (``TestHarnessWithDTM``), as well as a config to use that top-level system.