Merge remote-tracking branch 'origin/main' into rcbump
This commit is contained in:
4
.github/actions/create-conda-env/action.yml
vendored
4
.github/actions/create-conda-env/action.yml
vendored
@@ -10,8 +10,8 @@ runs:
|
|||||||
else
|
else
|
||||||
echo "Creating a conda environment for each toolchain with the toolchain installed"
|
echo "Creating a conda environment for each toolchain with the toolchain installed"
|
||||||
conda activate base
|
conda activate base
|
||||||
conda-lock install -n ${{ env.conda-env-name-no-time }}-$(date --date "${{ env.workflow-timestamp }}" +%Y%m%d)-riscv-tools ./conda-reqs/conda-lock-reqs/conda-requirements-riscv-tools-linux-64.conda-lock.yml
|
conda-lock install --conda $(which conda) -n ${{ env.conda-env-name-no-time }}-$(date --date "${{ env.workflow-timestamp }}" +%Y%m%d)-riscv-tools ./conda-reqs/conda-lock-reqs/conda-requirements-riscv-tools-linux-64.conda-lock.yml
|
||||||
conda-lock install -n ${{ env.conda-env-name-no-time }}-$(date --date "${{ env.workflow-timestamp }}" +%Y%m%d)-esp-tools ./conda-reqs/conda-lock-reqs/conda-requirements-esp-tools-linux-64.conda-lock.yml
|
conda-lock install --conda $(which conda) -n ${{ env.conda-env-name-no-time }}-$(date --date "${{ env.workflow-timestamp }}" +%Y%m%d)-esp-tools ./conda-reqs/conda-lock-reqs/conda-requirements-esp-tools-linux-64.conda-lock.yml
|
||||||
conda deactivate
|
conda deactivate
|
||||||
|
|
||||||
echo "Add extra toolchain collateral to RISC-V install area"
|
echo "Add extra toolchain collateral to RISC-V install area"
|
||||||
|
|||||||
7
.github/scripts/install-conda.sh
vendored
7
.github/scripts/install-conda.sh
vendored
@@ -145,15 +145,16 @@ else
|
|||||||
$SUDO bash ./install_conda.sh -b -p "$CONDA_INSTALL_PREFIX" $conda_install_extra
|
$SUDO bash ./install_conda.sh -b -p "$CONDA_INSTALL_PREFIX" $conda_install_extra
|
||||||
rm ./install_conda.sh
|
rm ./install_conda.sh
|
||||||
|
|
||||||
|
# get most up-to-date conda version
|
||||||
|
"${DRY_RUN_ECHO[@]}" $SUDO "$CONDA_EXE" update $DRY_RUN_OPTION -y -n base -c conda-forge conda
|
||||||
|
|
||||||
# see https://conda-forge.org/docs/user/tipsandtricks.html#multiple-channels
|
# see https://conda-forge.org/docs/user/tipsandtricks.html#multiple-channels
|
||||||
# for more information on flexible channel_priority
|
# for more information on flexible channel_priority
|
||||||
"${DRY_RUN_ECHO[@]}" $SUDO "$CONDA_EXE" config --system --set channel_priority flexible
|
"${DRY_RUN_ECHO[@]}" $SUDO "$CONDA_EXE" config --system --set channel_priority flexible
|
||||||
# By default, don't mess with people's PS1, I personally find it annoying
|
# By default, don't mess with people's PS1, I personally find it annoying
|
||||||
"${DRY_RUN_ECHO[@]}" $SUDO "$CONDA_EXE" config --system --set changeps1 false
|
"${DRY_RUN_ECHO[@]}" $SUDO "$CONDA_EXE" config --system --set changeps1 false
|
||||||
# don't automatically activate the 'base' environment when intializing shells
|
# don't automatically activate the 'base' environment when initializing shells
|
||||||
"${DRY_RUN_ECHO[@]}" $SUDO "$CONDA_EXE" config --system --set auto_activate_base false
|
"${DRY_RUN_ECHO[@]}" $SUDO "$CONDA_EXE" config --system --set auto_activate_base false
|
||||||
# don't automatically update conda to avoid https://github.com/conda-forge/conda-libmamba-solver-feedstock/issues/2
|
|
||||||
"${DRY_RUN_ECHO[@]}" $SUDO "$CONDA_EXE" config --system --set auto_update_conda false
|
|
||||||
# automatically use the ucb-bar channel for specific packages https://anaconda.org/ucb-bar/repo
|
# automatically use the ucb-bar channel for specific packages https://anaconda.org/ucb-bar/repo
|
||||||
"${DRY_RUN_ECHO[@]}" $SUDO "$CONDA_EXE" config --system --add channels ucb-bar
|
"${DRY_RUN_ECHO[@]}" $SUDO "$CONDA_EXE" config --system --add channels ucb-bar
|
||||||
|
|
||||||
|
|||||||
@@ -14,8 +14,9 @@ cd $REMOTE_CHIPYARD_DIR
|
|||||||
./scripts/init-submodules-no-riscv-tools.sh --force
|
./scripts/init-submodules-no-riscv-tools.sh --force
|
||||||
|
|
||||||
# Run Firesim Scala Tests
|
# Run Firesim Scala Tests
|
||||||
export FIRESIM_ENV_SOURCED=1;
|
export FIRESIM_ENV_SOURCED=1
|
||||||
export COURSIER_CACHE=$REMOTE_COURSIER_CACHE
|
export COURSIER_CACHE=$REMOTE_COURSIER_CACHE
|
||||||
export JVM_MEMORY=10G
|
export JVM_MEMORY=10G
|
||||||
export JAVA_TMP_DIR=$REMOTE_JAVA_TMP_DIR
|
export JAVA_TMP_DIR=$REMOTE_JAVA_TMP_DIR
|
||||||
|
export TEST_DISABLE_VIVADO=1
|
||||||
make -C $REMOTE_FIRESIM_DIR TARGET_SBT_PROJECT="{file:$REMOTE_CHIPYARD_DIR}firechip" testOnly ${mapping[$1]}
|
make -C $REMOTE_FIRESIM_DIR TARGET_SBT_PROJECT="{file:$REMOTE_CHIPYARD_DIR}firechip" testOnly ${mapping[$1]}
|
||||||
|
|||||||
9
.github/workflows/chipyard-full-flow.yml
vendored
9
.github/workflows/chipyard-full-flow.yml
vendored
@@ -65,7 +65,7 @@ jobs:
|
|||||||
name: setup-repo
|
name: setup-repo
|
||||||
needs: [change-filters, cancel-prior-workflows]
|
needs: [change-filters, cancel-prior-workflows]
|
||||||
if: needs.change-filters.outputs.needs-rtl == 'true'
|
if: needs.change-filters.outputs.needs-rtl == 'true'
|
||||||
runs-on: ferry
|
runs-on: jktqos
|
||||||
steps:
|
steps:
|
||||||
- name: Delete old checkout
|
- name: Delete old checkout
|
||||||
run: |
|
run: |
|
||||||
@@ -88,7 +88,7 @@ jobs:
|
|||||||
run-cfg-finder:
|
run-cfg-finder:
|
||||||
name: run-cfg-finder
|
name: run-cfg-finder
|
||||||
needs: [setup-repo]
|
needs: [setup-repo]
|
||||||
runs-on: ferry
|
runs-on: jktqos
|
||||||
steps:
|
steps:
|
||||||
- name: Run config finder
|
- name: Run config finder
|
||||||
run: |
|
run: |
|
||||||
@@ -101,7 +101,7 @@ jobs:
|
|||||||
run-tutorial:
|
run-tutorial:
|
||||||
name: run-tutorial
|
name: run-tutorial
|
||||||
needs: [setup-repo]
|
needs: [setup-repo]
|
||||||
runs-on: ferry
|
runs-on: jktqos
|
||||||
steps:
|
steps:
|
||||||
- name: Run smoke test
|
- name: Run smoke test
|
||||||
run: |
|
run: |
|
||||||
@@ -168,9 +168,10 @@ jobs:
|
|||||||
cleanup:
|
cleanup:
|
||||||
name: cleanup
|
name: cleanup
|
||||||
needs: [run-tutorial]
|
needs: [run-tutorial]
|
||||||
runs-on: ferry
|
runs-on: jktqos
|
||||||
if: ${{ always() }}
|
if: ${{ always() }}
|
||||||
steps:
|
steps:
|
||||||
- name: Delete repo copy and conda env
|
- name: Delete repo copy and conda env
|
||||||
run: |
|
run: |
|
||||||
rm -rf ${{ env.REMOTE_WORK_DIR }}
|
rm -rf ${{ env.REMOTE_WORK_DIR }}
|
||||||
|
rm -rf ${{ env.JAVA_TMP_DIR }}
|
||||||
|
|||||||
18
.github/workflows/chipyard-run-tests.yml
vendored
18
.github/workflows/chipyard-run-tests.yml
vendored
@@ -166,7 +166,7 @@ jobs:
|
|||||||
- name: Generate keys
|
- name: Generate keys
|
||||||
id: genkey
|
id: genkey
|
||||||
run: |
|
run: |
|
||||||
echo "::set-output name=extra-tests-cache-key::extra-tests-${{ github.sha }}"
|
echo "extra-tests-cache-key=extra-tests-${{ github.sha }}" >> $GITHUB_OUTPUT
|
||||||
- uses: actions/cache@v3
|
- uses: actions/cache@v3
|
||||||
id: build-extra-tools-cache
|
id: build-extra-tools-cache
|
||||||
with:
|
with:
|
||||||
@@ -178,11 +178,11 @@ jobs:
|
|||||||
conda activate ${{ env.conda-env-name-no-time }}-$(date --date "${{ env.workflow-timestamp }}" +%Y%m%d)-riscv-tools
|
conda activate ${{ env.conda-env-name-no-time }}-$(date --date "${{ env.workflow-timestamp }}" +%Y%m%d)-riscv-tools
|
||||||
.github/scripts/build-extra-tests.sh
|
.github/scripts/build-extra-tests.sh
|
||||||
|
|
||||||
create-conda-env-knight:
|
create-conda-env-jktgz:
|
||||||
name: create-conda-env-knight
|
name: create-conda-env-jktgz
|
||||||
needs: [change-filters, cancel-prior-workflows]
|
needs: [change-filters, cancel-prior-workflows]
|
||||||
if: needs.change-filters.outputs.needs-rtl == 'true'
|
if: needs.change-filters.outputs.needs-rtl == 'true'
|
||||||
runs-on: knight
|
runs-on: jktgz
|
||||||
steps:
|
steps:
|
||||||
- name: Delete old checkout
|
- name: Delete old checkout
|
||||||
run: |
|
run: |
|
||||||
@@ -199,11 +199,11 @@ jobs:
|
|||||||
- name: Create conda env
|
- name: Create conda env
|
||||||
uses: ./.github/actions/create-conda-env
|
uses: ./.github/actions/create-conda-env
|
||||||
|
|
||||||
create-conda-env-ferry:
|
create-conda-env-jktqos:
|
||||||
name: create-conda-env-ferry
|
name: create-conda-env-jktqos
|
||||||
needs: [change-filters, cancel-prior-workflows]
|
needs: [change-filters, cancel-prior-workflows]
|
||||||
if: needs.change-filters.outputs.needs-rtl == 'true'
|
if: needs.change-filters.outputs.needs-rtl == 'true'
|
||||||
runs-on: ferry
|
runs-on: jktqos
|
||||||
steps:
|
steps:
|
||||||
- name: Delete old checkout
|
- name: Delete old checkout
|
||||||
run: |
|
run: |
|
||||||
@@ -225,7 +225,7 @@ jobs:
|
|||||||
# When adding new prep jobs, please add them to `needs` below
|
# When adding new prep jobs, please add them to `needs` below
|
||||||
setup-complete:
|
setup-complete:
|
||||||
name: setup-complete
|
name: setup-complete
|
||||||
needs: [create-conda-env-knight, create-conda-env-ferry, build-extra-tests]
|
needs: [create-conda-env-jktgz, create-conda-env-jktqos, build-extra-tests]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Set up complete
|
- name: Set up complete
|
||||||
@@ -393,7 +393,7 @@ jobs:
|
|||||||
chipyard-spike-gemmini-run-tests:
|
chipyard-spike-gemmini-run-tests:
|
||||||
name: chipyard-spike-gemmini-run-tests
|
name: chipyard-spike-gemmini-run-tests
|
||||||
needs: prepare-chipyard-accels # technically doesn't depend on RTL but should be after the build.sh for Gemmini
|
needs: prepare-chipyard-accels # technically doesn't depend on RTL but should be after the build.sh for Gemmini
|
||||||
runs-on: ferry
|
runs-on: jktqos
|
||||||
steps:
|
steps:
|
||||||
- name: Delete old checkout
|
- name: Delete old checkout
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
56
.github/workflows/config/release-notes.json
vendored
Normal file
56
.github/workflows/config/release-notes.json
vendored
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
{
|
||||||
|
"categories": [
|
||||||
|
{
|
||||||
|
"title": "## Added",
|
||||||
|
"labels": ["changelog:added"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "## Changed",
|
||||||
|
"labels": ["changelog:changed"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "## Fixed",
|
||||||
|
"labels": ["changelog:fixed"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "## Removed",
|
||||||
|
"labels": ["changelog:removed"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "## Uncategorized",
|
||||||
|
"labels": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ignore_labels": [
|
||||||
|
"changelog:omit"
|
||||||
|
],
|
||||||
|
"sort": {
|
||||||
|
"order": "ASC",
|
||||||
|
"on_property": "mergedAt"
|
||||||
|
},
|
||||||
|
"template": "${{CHANGELOG}}\n\n**Full Changelog:** ${{RELEASE_DIFF}}\n",
|
||||||
|
"pr_template": "- ${{TITLE}} (by @${{AUTHOR}} in ${{URL}})${{RELEASE_NOTES}}",
|
||||||
|
"empty_template": "- no changes",
|
||||||
|
"transformers": [
|
||||||
|
{
|
||||||
|
"pattern": "<!--.*-->",
|
||||||
|
"flags": "gus",
|
||||||
|
"target": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"custom_placeholders": [
|
||||||
|
{
|
||||||
|
"name": "RELEASE_NOTES",
|
||||||
|
"source": "BODY",
|
||||||
|
"transformer": {
|
||||||
|
"pattern": ".*#### Release Notes(?:[\n\\s]|(?:<!--.*?-->))*((?:\\S(?!!--)).*?)[\n\\s]*\n#.*",
|
||||||
|
"flags": "gus",
|
||||||
|
"target": "\n $1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"trim_values": false,
|
||||||
|
"max_tags_to_fetch": 200,
|
||||||
|
"max_pull_requests": 500,
|
||||||
|
"max_back_track_time_days": 365
|
||||||
|
}
|
||||||
51
.github/workflows/release-notes.yml
vendored
Normal file
51
.github/workflows/release-notes.yml
vendored
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
# adapted from https://github.com/chipsalliance/chisel/blob/main/.github/workflows/release-notes.yml
|
||||||
|
|
||||||
|
name: Generate Release Notes
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types: [created]
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
toTag:
|
||||||
|
description: 'Tag or ref for which to generate release notes'
|
||||||
|
required: true
|
||||||
|
fromTag:
|
||||||
|
# If you leave this blank, it'll select previous SemVer version
|
||||||
|
# WARNING: Cannot use anything older than a005498 because of the git tree merge
|
||||||
|
description: 'Tag or ref from which to start generating release notes'
|
||||||
|
required: false
|
||||||
|
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
generate_release_notes:
|
||||||
|
name: Generate Release Notes
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Build Release Notes
|
||||||
|
id: release-notes
|
||||||
|
uses: mikepenz/release-changelog-builder-action@v3.7.0
|
||||||
|
with:
|
||||||
|
configuration: .github/workflows/config/release-notes.json
|
||||||
|
failOnError: true
|
||||||
|
# Amazingly, on release where the inputs are empty, this just does the right thing
|
||||||
|
# The "toTag" is the released tag, and the "fromTag" is the previous tag according to SemVer
|
||||||
|
fromTag: ${{ github.event.inputs.fromTag }}
|
||||||
|
toTag: ${{ github.event.inputs.toTag }}
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- name: Report Release Notes
|
||||||
|
# Put output through env variable to make it robust to quotes
|
||||||
|
env:
|
||||||
|
CHANGELOG: ${{steps.release-notes.outputs.changelog}}
|
||||||
|
run: echo "$CHANGELOG" >> $GITHUB_STEP_SUMMARY
|
||||||
|
- name: Upload Release Notes (on release)
|
||||||
|
if: github.event_name == 'release'
|
||||||
|
uses: softprops/action-gh-release@v0.1.15
|
||||||
|
with:
|
||||||
|
body: ${{ steps.release-notes.outputs.changelog }}
|
||||||
|
- name: Error on uncategorized PRs
|
||||||
|
if: steps.release-notes.outputs.uncategorized_prs != 0
|
||||||
|
run: exit 1
|
||||||
24
.github/workflows/require-label.yml
vendored
Normal file
24
.github/workflows/require-label.yml
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# adapted from https://github.com/chipsalliance/chisel/blob/main/.github/workflows/require-label.yml
|
||||||
|
|
||||||
|
name: Require Release Notes Label
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
types:
|
||||||
|
- opened
|
||||||
|
- synchronize
|
||||||
|
- reopened
|
||||||
|
- labeled
|
||||||
|
- unlabeled
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
check_labels:
|
||||||
|
name: Check Labels
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: docker://agilepathway/pull-request-label-checker:v1.4.25
|
||||||
|
with:
|
||||||
|
one_of: changelog:added,changelog:changed,changelog:fixed,changelog:omit,changelog:removed
|
||||||
|
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -27,3 +27,4 @@ project/project/
|
|||||||
.ivy2
|
.ivy2
|
||||||
.sbt
|
.sbt
|
||||||
.classpath_cache/
|
.classpath_cache/
|
||||||
|
.vscode/
|
||||||
|
|||||||
18
.mergify.yml
18
.mergify.yml
@@ -22,21 +22,3 @@ pull_request_rules:
|
|||||||
actions:
|
actions:
|
||||||
label:
|
label:
|
||||||
add: [Backport]
|
add: [Backport]
|
||||||
|
|
||||||
- name: check PR has changelog label
|
|
||||||
conditions:
|
|
||||||
- base=main
|
|
||||||
actions:
|
|
||||||
post_check:
|
|
||||||
success_conditions:
|
|
||||||
- "label~=^changelog:"
|
|
||||||
title: |
|
|
||||||
{% if check_succeed %}
|
|
||||||
Labeled for changelog
|
|
||||||
{% else %}
|
|
||||||
Needs label for changelog
|
|
||||||
{% endif %}
|
|
||||||
summary: |
|
|
||||||
{% if not check_succeed %}
|
|
||||||
Your pull request must have a changelog label (e.g. `changelog: ...`).
|
|
||||||
{% endif %}
|
|
||||||
|
|||||||
@@ -122,7 +122,8 @@ lazy val rocketchip = freshProject("rocketchip", rocketChipDir)
|
|||||||
libraryDependencies ++= Seq(
|
libraryDependencies ++= Seq(
|
||||||
"org.scala-lang" % "scala-reflect" % scalaVersion.value,
|
"org.scala-lang" % "scala-reflect" % scalaVersion.value,
|
||||||
"org.json4s" %% "json4s-jackson" % "3.6.6",
|
"org.json4s" %% "json4s-jackson" % "3.6.6",
|
||||||
"org.scalatest" %% "scalatest" % "3.2.0" % "test"
|
"org.scalatest" %% "scalatest" % "3.2.0" % "test",
|
||||||
|
"org.scala-graph" %% "graph-core" % "1.13.5"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.settings( // Settings for scalafix
|
.settings( // Settings for scalafix
|
||||||
|
|||||||
@@ -20,7 +20,8 @@ HELP_COMPILATION_VARIABLES += \
|
|||||||
" ENABLE_YOSYS_FLOW = if set, add compilation flags to enable the vlsi flow for yosys(tutorial flow)" \
|
" ENABLE_YOSYS_FLOW = if set, add compilation flags to enable the vlsi flow for yosys(tutorial flow)" \
|
||||||
" EXTRA_CHISEL_OPTIONS = additional options to pass to the Chisel compiler" \
|
" EXTRA_CHISEL_OPTIONS = additional options to pass to the Chisel compiler" \
|
||||||
" EXTRA_BASE_FIRRTL_OPTIONS = additional options to pass to the Scala FIRRTL compiler" \
|
" EXTRA_BASE_FIRRTL_OPTIONS = additional options to pass to the Scala FIRRTL compiler" \
|
||||||
" MFC_BASE_LOWERING_OPTIONS = override lowering options to pass to the MLIR FIRRTL compiler"
|
" MFC_BASE_LOWERING_OPTIONS = override lowering options to pass to the MLIR FIRRTL compiler" \
|
||||||
|
" ASPECTS = comma separated list of Chisel aspect flows to run (e.x. chipyard.upf.ChipTopUPFAspect)"
|
||||||
|
|
||||||
EXTRA_GENERATOR_REQS ?= $(BOOTROM_TARGETS)
|
EXTRA_GENERATOR_REQS ?= $(BOOTROM_TARGETS)
|
||||||
EXTRA_SIM_CXXFLAGS ?=
|
EXTRA_SIM_CXXFLAGS ?=
|
||||||
@@ -29,6 +30,11 @@ EXTRA_SIM_SOURCES ?=
|
|||||||
EXTRA_SIM_REQS ?=
|
EXTRA_SIM_REQS ?=
|
||||||
ENABLE_CUSTOM_FIRRTL_PASS += $(ENABLE_YOSYS_FLOW)
|
ENABLE_CUSTOM_FIRRTL_PASS += $(ENABLE_YOSYS_FLOW)
|
||||||
|
|
||||||
|
ifneq ($(ASPECTS), )
|
||||||
|
comma = ,
|
||||||
|
ASPECT_ARGS = $(foreach aspect, $(subst $(comma), , $(ASPECTS)), --with-aspect $(aspect))
|
||||||
|
endif
|
||||||
|
|
||||||
#----------------------------------------------------------------------------
|
#----------------------------------------------------------------------------
|
||||||
HELP_SIMULATION_VARIABLES += \
|
HELP_SIMULATION_VARIABLES += \
|
||||||
" EXTRA_SIM_FLAGS = additional runtime simulation flags (passed within +permissive)" \
|
" EXTRA_SIM_FLAGS = additional runtime simulation flags (passed within +permissive)" \
|
||||||
@@ -134,6 +140,7 @@ $(FIRRTL_FILE) $(ANNO_FILE) $(CHISEL_LOG_FILE) &: $(CHIPYARD_CLASSPATH_TARGETS)
|
|||||||
--name $(long_name) \
|
--name $(long_name) \
|
||||||
--top-module $(MODEL_PACKAGE).$(MODEL) \
|
--top-module $(MODEL_PACKAGE).$(MODEL) \
|
||||||
--legacy-configs $(CONFIG_PACKAGE):$(CONFIG) \
|
--legacy-configs $(CONFIG_PACKAGE):$(CONFIG) \
|
||||||
|
$(ASPECT_ARGS) \
|
||||||
$(EXTRA_CHISEL_OPTIONS)) | tee $(CHISEL_LOG_FILE))
|
$(EXTRA_CHISEL_OPTIONS)) | tee $(CHISEL_LOG_FILE))
|
||||||
|
|
||||||
define mfc_extra_anno_contents
|
define mfc_extra_anno_contents
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ dependencies:
|
|||||||
# bundle FireSim driver with deps into installer shell-script
|
# bundle FireSim driver with deps into installer shell-script
|
||||||
- constructor
|
- constructor
|
||||||
|
|
||||||
- gcc
|
- gcc<13
|
||||||
- gxx
|
- gxx<13
|
||||||
- sysroot_linux-64=2.17 # needed to match pre-built CI XRT glibc version
|
- sysroot_linux-64=2.17 # needed to match pre-built CI XRT glibc version
|
||||||
- conda-gcc-specs
|
- conda-gcc-specs
|
||||||
- binutils
|
- binutils
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -34,6 +34,13 @@ After Conda is installed and is on your ``PATH``, we need to install a version o
|
|||||||
For this you can use the system package manager like ``yum`` or ``apt`` to install ``git``.
|
For this you can use the system package manager like ``yum`` or ``apt`` to install ``git``.
|
||||||
This ``git`` is only used to first checkout the repository, we will later install a newer version of ``git`` with Conda.
|
This ``git`` is only used to first checkout the repository, we will later install a newer version of ``git`` with Conda.
|
||||||
|
|
||||||
|
Next, we install `libmamba <https://www.anaconda.com/blog/a-faster-conda-for-a-growing-community>`__ for much faster dependency solving when initially setting up the repository.
|
||||||
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
conda install -n base conda-libmamba-solver
|
||||||
|
conda config --set solver libmamba
|
||||||
|
|
||||||
Finally we need to install ``conda-lock`` into the ``base`` conda environment.
|
Finally we need to install ``conda-lock`` into the ``base`` conda environment.
|
||||||
This is done by the following:
|
This is done by the following:
|
||||||
|
|
||||||
@@ -42,7 +49,6 @@ This is done by the following:
|
|||||||
conda install -n base conda-lock=1.4
|
conda install -n base conda-lock=1.4
|
||||||
conda activate base
|
conda activate base
|
||||||
|
|
||||||
.. Note:: We also recommended switching to `libmamba <https://www.anaconda.com/blog/a-faster-conda-for-a-growing-community>`__ for much faster dependency solving.
|
|
||||||
|
|
||||||
Setting up the Chipyard Repo
|
Setting up the Chipyard Repo
|
||||||
-------------------------------------------
|
-------------------------------------------
|
||||||
|
|||||||
@@ -106,3 +106,22 @@ With the Synopsys plugin, hierarchical RTL and gate-level simulation is supporte
|
|||||||
* ``-$(VLSI_TOP)`` suffixes denote simulations/power analysis on a submodule in a hierarchical flow (remember to override this variable). Note that you must provide the testbenches for these modules since the default testbench only simulates a Chipyard-based ``ChipTop`` DUT instance.
|
* ``-$(VLSI_TOP)`` suffixes denote simulations/power analysis on a submodule in a hierarchical flow (remember to override this variable). Note that you must provide the testbenches for these modules since the default testbench only simulates a Chipyard-based ``ChipTop`` DUT instance.
|
||||||
|
|
||||||
The simulation configuration (e.g. binaries) can be edited for your design. See the ``Makefile`` and refer to Hammer's documentation for how to set up simulation parameters for your design.
|
The simulation configuration (e.g. binaries) can be edited for your design. See the ``Makefile`` and refer to Hammer's documentation for how to set up simulation parameters for your design.
|
||||||
|
|
||||||
|
UPF Generation Flow
|
||||||
|
-------------------------------
|
||||||
|
This VLSI flow experimentally supports generating Chisel-based `UPF <https://vlsitutorials.com/upf-low-power-vlsi/>`__ files using `Chisel Aspects <https://javadoc.io/doc/edu.berkeley.cs/chisel3_2.13/latest/chisel3/aop/Aspect.html>`__.
|
||||||
|
|
||||||
|
To generate UPF for any design, first modify the ``UPFInputs`` object in ``generators/chipyard/src/main/scala/upf/UPFInputs.scala`` to fit your design power specifications.
|
||||||
|
|
||||||
|
This involves filling in the ``upfInfo`` list with ``PowerDomainInput`` objects representing all the power domains you want in your design, along with specifying hierarchy and domain attributes.
|
||||||
|
|
||||||
|
The given example in ``UPFInputs`` corresponds to a dual-core Rocket config with 3 power domains (1 parent domain with all uncore modules and 2 children corresponding to the Rocket tiles).
|
||||||
|
|
||||||
|
To run the flow:
|
||||||
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
cd chipyard/vlsi
|
||||||
|
make verilog ASPECTS=chipyard.upf.ChipTopUPFAspect
|
||||||
|
|
||||||
|
The output UPF files will be dumped in ``vlsi/generated-src/upf``.
|
||||||
|
|||||||
@@ -35,6 +35,11 @@ extern std::map<long long int, backing_data_t> backing_mem_data;
|
|||||||
#define PLIC_BASE (0xc000000)
|
#define PLIC_BASE (0xc000000)
|
||||||
#define PLIC_SIZE (0x4000000)
|
#define PLIC_SIZE (0x4000000)
|
||||||
|
|
||||||
|
#define COSPIKE_PRINTF(...) { \
|
||||||
|
printf(__VA_ARGS__); \
|
||||||
|
fprintf(stderr, __VA_ARGS__); \
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct system_info_t {
|
typedef struct system_info_t {
|
||||||
std::string isa;
|
std::string isa;
|
||||||
int pmpregions;
|
int pmpregions;
|
||||||
@@ -42,19 +47,21 @@ typedef struct system_info_t {
|
|||||||
uint64_t mem0_size;
|
uint64_t mem0_size;
|
||||||
int nharts;
|
int nharts;
|
||||||
std::vector<char> bootrom;
|
std::vector<char> bootrom;
|
||||||
|
std::string priv;
|
||||||
};
|
};
|
||||||
|
|
||||||
class read_override_device_t : public abstract_device_t {
|
class read_override_device_t : public abstract_device_t {
|
||||||
public:
|
public:
|
||||||
read_override_device_t(std::string n, reg_t sz) : was_read_from(false), size(size), name(n) { };
|
read_override_device_t(std::string n, reg_t sz) : was_read_from(false), size(sz), name(n) { };
|
||||||
bool load(reg_t addr, size_t len, uint8_t* bytes) {
|
virtual bool load(reg_t addr, size_t len, uint8_t* bytes) override {
|
||||||
if (addr + len < addr || addr + len > size) return false;
|
if (addr + len > size) return false;
|
||||||
printf("Read from device %s at %lx\n", name.c_str(), addr);
|
COSPIKE_PRINTF("Read from device %s at %lx\n", name.c_str(), addr);
|
||||||
was_read_from = true;
|
was_read_from = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool store(reg_t addr, size_t len, const uint8_t* bytes) {
|
virtual bool store(reg_t addr, size_t len, const uint8_t* bytes) override {
|
||||||
return (addr + len >= addr && addr + len <= size);
|
COSPIKE_PRINTF("Store to device %s at %lx\n", name.c_str(), addr);
|
||||||
|
return (addr + len <= size);
|
||||||
}
|
}
|
||||||
bool was_read_from;
|
bool was_read_from;
|
||||||
private:
|
private:
|
||||||
@@ -70,7 +77,7 @@ reg_t fromhost_addr = 0;
|
|||||||
reg_t cospike_timeout = 0;
|
reg_t cospike_timeout = 0;
|
||||||
std::set<reg_t> magic_addrs;
|
std::set<reg_t> magic_addrs;
|
||||||
cfg_t* cfg;
|
cfg_t* cfg;
|
||||||
std::vector<read_override_device_t*> read_override_devices;
|
std::vector<std::shared_ptr<read_override_device_t>> read_override_devices;
|
||||||
|
|
||||||
static std::vector<std::pair<reg_t, mem_t*>> make_mems(const std::vector<mem_cfg_t> &layout)
|
static std::vector<std::pair<reg_t, mem_t*>> make_mems(const std::vector<mem_cfg_t> &layout)
|
||||||
{
|
{
|
||||||
@@ -82,7 +89,7 @@ static std::vector<std::pair<reg_t, mem_t*>> make_mems(const std::vector<mem_cfg
|
|||||||
return mems;
|
return mems;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void cospike_set_sysinfo(char* isa, int pmpregions,
|
extern "C" void cospike_set_sysinfo(char* isa, char* priv, int pmpregions,
|
||||||
long long int mem0_base, long long int mem0_size,
|
long long int mem0_base, long long int mem0_size,
|
||||||
int nharts,
|
int nharts,
|
||||||
char* bootrom
|
char* bootrom
|
||||||
@@ -91,6 +98,7 @@ extern "C" void cospike_set_sysinfo(char* isa, int pmpregions,
|
|||||||
info = new system_info_t;
|
info = new system_info_t;
|
||||||
// technically the targets aren't zicntr compliant, but they implement the zicntr registers
|
// technically the targets aren't zicntr compliant, but they implement the zicntr registers
|
||||||
info->isa = std::string(isa) + "_zicntr";
|
info->isa = std::string(isa) + "_zicntr";
|
||||||
|
info->priv = std::string(priv);
|
||||||
info->pmpregions = pmpregions;
|
info->pmpregions = pmpregions;
|
||||||
info->mem0_base = mem0_base;
|
info->mem0_base = mem0_base;
|
||||||
info->mem0_size = mem0_size;
|
info->mem0_size = mem0_size;
|
||||||
@@ -118,7 +126,7 @@ extern "C" void cospike_cosim(long long int cycle,
|
|||||||
assert(info);
|
assert(info);
|
||||||
|
|
||||||
if (unlikely(!sim)) {
|
if (unlikely(!sim)) {
|
||||||
printf("Configuring spike cosim\n");
|
COSPIKE_PRINTF("Configuring spike cosim\n");
|
||||||
std::vector<mem_cfg_t> mem_cfg;
|
std::vector<mem_cfg_t> mem_cfg;
|
||||||
std::vector<size_t> hartids;
|
std::vector<size_t> hartids;
|
||||||
mem_cfg.push_back(mem_cfg_t(info->mem0_base, info->mem0_size));
|
mem_cfg.push_back(mem_cfg_t(info->mem0_base, info->mem0_size));
|
||||||
@@ -128,7 +136,7 @@ extern "C" void cospike_cosim(long long int cycle,
|
|||||||
cfg = new cfg_t(std::make_pair(0, 0),
|
cfg = new cfg_t(std::make_pair(0, 0),
|
||||||
nullptr,
|
nullptr,
|
||||||
info->isa.c_str(),
|
info->isa.c_str(),
|
||||||
"MSU",
|
info->priv.c_str(),
|
||||||
"vlen:128,elen:64",
|
"vlen:128,elen:64",
|
||||||
false,
|
false,
|
||||||
endianness_little,
|
endianness_little,
|
||||||
@@ -146,26 +154,26 @@ extern "C" void cospike_cosim(long long int cycle,
|
|||||||
assert(info->bootrom.size() < default_boot_rom_size);
|
assert(info->bootrom.size() < default_boot_rom_size);
|
||||||
info->bootrom.resize(default_boot_rom_size);
|
info->bootrom.resize(default_boot_rom_size);
|
||||||
|
|
||||||
rom_device_t *boot_rom = new rom_device_t(info->bootrom);
|
std::shared_ptr<rom_device_t> boot_rom = std::make_shared<rom_device_t>(info->bootrom);
|
||||||
mem_t *boot_addr_reg = new mem_t(0x1000);
|
std::shared_ptr<mem_t> boot_addr_reg = std::make_shared<mem_t>(0x1000);
|
||||||
uint64_t default_boot_addr = 0x80000000;
|
uint64_t default_boot_addr = 0x80000000;
|
||||||
boot_addr_reg->store(0, 8, (const uint8_t*)(&default_boot_addr));
|
boot_addr_reg.get()->store(0, 8, (const uint8_t*)(&default_boot_addr));
|
||||||
|
|
||||||
read_override_device_t* clint = new read_override_device_t("clint", CLINT_SIZE);
|
std::shared_ptr<read_override_device_t> clint = std::make_shared<read_override_device_t>("clint", CLINT_SIZE);
|
||||||
read_override_device_t* uart = new read_override_device_t("uart", UART_SIZE);
|
std::shared_ptr<read_override_device_t> uart = std::make_shared<read_override_device_t>("uart", UART_SIZE);
|
||||||
read_override_device_t* plic = new read_override_device_t("plic", PLIC_SIZE);
|
std::shared_ptr<read_override_device_t> plic = std::make_shared<read_override_device_t>("plic", PLIC_SIZE);
|
||||||
|
|
||||||
read_override_devices.push_back(clint);
|
read_override_devices.push_back(clint);
|
||||||
read_override_devices.push_back(uart);
|
read_override_devices.push_back(uart);
|
||||||
read_override_devices.push_back(plic);
|
read_override_devices.push_back(plic);
|
||||||
|
|
||||||
std::vector<std::pair<reg_t, abstract_device_t*>> plugin_devices;
|
std::vector<std::pair<reg_t, std::shared_ptr<abstract_device_t>>> devices;
|
||||||
// The device map is hardcoded here for now
|
// The device map is hardcoded here for now
|
||||||
plugin_devices.push_back(std::pair(0x4000, boot_addr_reg));
|
devices.push_back(std::pair(0x4000, boot_addr_reg));
|
||||||
plugin_devices.push_back(std::pair(default_boot_rom_addr, boot_rom));
|
devices.push_back(std::pair(default_boot_rom_addr, boot_rom));
|
||||||
plugin_devices.push_back(std::pair(CLINT_BASE, clint));
|
devices.push_back(std::pair(CLINT_BASE, clint));
|
||||||
plugin_devices.push_back(std::pair(UART_BASE, uart));
|
devices.push_back(std::pair(UART_BASE, uart));
|
||||||
plugin_devices.push_back(std::pair(PLIC_BASE, plic));
|
devices.push_back(std::pair(PLIC_BASE, plic));
|
||||||
|
|
||||||
s_vpi_vlog_info vinfo;
|
s_vpi_vlog_info vinfo;
|
||||||
if (!vpi_get_vlog_info(&vinfo))
|
if (!vpi_get_vlog_info(&vinfo))
|
||||||
@@ -200,16 +208,17 @@ extern "C" void cospike_cosim(long long int cycle,
|
|||||||
.support_impebreak = true
|
.support_impebreak = true
|
||||||
};
|
};
|
||||||
|
|
||||||
printf("isa string: %s\n", info->isa.c_str());
|
COSPIKE_PRINTF("isa string: %s\n", info->isa.c_str());
|
||||||
printf("htif args: ");
|
COSPIKE_PRINTF("htif args: ");
|
||||||
for (int i = 0; i < htif_args.size(); i++) {
|
for (int i = 0; i < htif_args.size(); i++) {
|
||||||
printf("%s", htif_args[i].c_str());
|
COSPIKE_PRINTF("%s", htif_args[i].c_str());
|
||||||
}
|
}
|
||||||
printf("\n");
|
COSPIKE_PRINTF("\n");
|
||||||
|
|
||||||
|
std::vector<const device_factory_t*> plugin_device_factories;
|
||||||
sim = new sim_t(cfg, false,
|
sim = new sim_t(cfg, false,
|
||||||
mems,
|
mems,
|
||||||
plugin_devices,
|
plugin_device_factories,
|
||||||
htif_args,
|
htif_args,
|
||||||
dm_config,
|
dm_config,
|
||||||
nullptr,
|
nullptr,
|
||||||
@@ -218,6 +227,8 @@ extern "C" void cospike_cosim(long long int cycle,
|
|||||||
false,
|
false,
|
||||||
nullptr
|
nullptr
|
||||||
);
|
);
|
||||||
|
for (auto &it : devices)
|
||||||
|
sim->add_device(it.first, it.second);
|
||||||
|
|
||||||
#ifdef COSPIKE_SIMDRAM
|
#ifdef COSPIKE_SIMDRAM
|
||||||
// match sim_t's backing memory with the SimDRAM memory
|
// match sim_t's backing memory with the SimDRAM memory
|
||||||
@@ -227,9 +238,9 @@ extern "C" void cospike_cosim(long long int cycle,
|
|||||||
for (auto& pair : backing_mem_data) {
|
for (auto& pair : backing_mem_data) {
|
||||||
size_t base = pair.first;
|
size_t base = pair.first;
|
||||||
size_t size = pair.second.size;
|
size_t size = pair.second.size;
|
||||||
printf("Matching spike memory initial state for region %lx-%lx\n", base, base + size);
|
COSPIKE_PRINTF("Matching spike memory initial state for region %lx-%lx\n", base, base + size);
|
||||||
if (!temp_mem_bus.store(base, size, pair.second.data)) {
|
if (!temp_mem_bus.store(base, size, pair.second.data)) {
|
||||||
printf("Error, unable to match memory at address %lx\n", base);
|
COSPIKE_PRINTF("Error, unable to match memory at address %lx\n", base);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -249,17 +260,17 @@ extern "C" void cospike_cosim(long long int cycle,
|
|||||||
sim->set_debug(cospike_debug);
|
sim->set_debug(cospike_debug);
|
||||||
sim->set_histogram(true);
|
sim->set_histogram(true);
|
||||||
sim->set_procs_debug(cospike_debug);
|
sim->set_procs_debug(cospike_debug);
|
||||||
printf("Setting up htif for spike cosim\n");
|
COSPIKE_PRINTF("Setting up htif for spike cosim\n");
|
||||||
((htif_t*)sim)->start();
|
((htif_t*)sim)->start();
|
||||||
printf("Spike cosim started\n");
|
COSPIKE_PRINTF("Spike cosim started\n");
|
||||||
tohost_addr = ((htif_t*)sim)->get_tohost_addr();
|
tohost_addr = ((htif_t*)sim)->get_tohost_addr();
|
||||||
fromhost_addr = ((htif_t*)sim)->get_fromhost_addr();
|
fromhost_addr = ((htif_t*)sim)->get_fromhost_addr();
|
||||||
printf("Tohost : %lx\n", tohost_addr);
|
COSPIKE_PRINTF("Tohost : %lx\n", tohost_addr);
|
||||||
printf("Fromhost: %lx\n", fromhost_addr);
|
COSPIKE_PRINTF("Fromhost: %lx\n", fromhost_addr);
|
||||||
printf("BootROM base : %lx\n", default_boot_rom_addr);
|
COSPIKE_PRINTF("BootROM base : %lx\n", default_boot_rom_addr);
|
||||||
printf("BootROM size : %lx\n", boot_rom->contents().size());
|
COSPIKE_PRINTF("BootROM size : %lx\n", boot_rom->contents().size());
|
||||||
printf("Memory base : %lx\n", info->mem0_base);
|
COSPIKE_PRINTF("Memory base : %lx\n", info->mem0_base);
|
||||||
printf("Memory size : %lx\n", info->mem0_size);
|
COSPIKE_PRINTF("Memory size : %lx\n", info->mem0_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv & 0x4) { // debug
|
if (priv & 0x4) { // debug
|
||||||
@@ -268,7 +279,7 @@ extern "C" void cospike_cosim(long long int cycle,
|
|||||||
|
|
||||||
if (cospike_timeout && cycle > cospike_timeout) {
|
if (cospike_timeout && cycle > cospike_timeout) {
|
||||||
if (sim) {
|
if (sim) {
|
||||||
printf("Cospike reached timeout cycles = %ld, terminating\n", cospike_timeout);
|
COSPIKE_PRINTF("Cospike reached timeout cycles = %ld, terminating\n", cospike_timeout);
|
||||||
delete sim;
|
delete sim;
|
||||||
}
|
}
|
||||||
exit(0);
|
exit(0);
|
||||||
@@ -279,7 +290,7 @@ extern "C" void cospike_cosim(long long int cycle,
|
|||||||
state_t* s = p->get_state();
|
state_t* s = p->get_state();
|
||||||
#ifdef COSPIKE_DTM
|
#ifdef COSPIKE_DTM
|
||||||
if (dtm && dtm->loadarch_done && !spike_loadarch_done) {
|
if (dtm && dtm->loadarch_done && !spike_loadarch_done) {
|
||||||
printf("Restoring spike state from testchip_dtm loadarch\n");
|
COSPIKE_PRINTF("Restoring spike state from testchip_dtm loadarch\n");
|
||||||
// copy the loadarch state into the cosim
|
// copy the loadarch state into the cosim
|
||||||
loadarch_state_t &ls = dtm->loadarch_state[hartid];
|
loadarch_state_t &ls = dtm->loadarch_state[hartid];
|
||||||
s->pc = ls.pc;
|
s->pc = ls.pc;
|
||||||
@@ -311,11 +322,11 @@ extern "C" void cospike_cosim(long long int cycle,
|
|||||||
RESTORE(CSR_MCYCLE , mcycle);
|
RESTORE(CSR_MCYCLE , mcycle);
|
||||||
RESTORE(CSR_MINSTRET , minstret);
|
RESTORE(CSR_MINSTRET , minstret);
|
||||||
if (ls.VLEN != p->VU.VLEN) {
|
if (ls.VLEN != p->VU.VLEN) {
|
||||||
printf("VLEN mismatch loadarch: $d != spike: $d\n", ls.VLEN, p->VU.VLEN);
|
COSPIKE_PRINTF("VLEN mismatch loadarch: $d != spike: $d\n", ls.VLEN, p->VU.VLEN);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
if (ls.ELEN != p->VU.ELEN) {
|
if (ls.ELEN != p->VU.ELEN) {
|
||||||
printf("ELEN mismatch loadarch: $d != spike: $d\n", ls.ELEN, p->VU.ELEN);
|
COSPIKE_PRINTF("ELEN mismatch loadarch: $d != spike: $d\n", ls.ELEN, p->VU.ELEN);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < 32; i++) {
|
for (size_t i = 0; i < 32; i++) {
|
||||||
@@ -335,7 +346,7 @@ extern "C" void cospike_cosim(long long int cycle,
|
|||||||
bool mtip_interrupt = interrupt_cause == 0x7;
|
bool mtip_interrupt = interrupt_cause == 0x7;
|
||||||
bool debug_interrupt = interrupt_cause == 0xe;
|
bool debug_interrupt = interrupt_cause == 0xe;
|
||||||
if (raise_interrupt) {
|
if (raise_interrupt) {
|
||||||
printf("%d interrupt %lx\n", cycle, cause);
|
COSPIKE_PRINTF("%d interrupt %lx\n", cycle, cause);
|
||||||
|
|
||||||
if (ssip_interrupt || stip_interrupt) {
|
if (ssip_interrupt || stip_interrupt) {
|
||||||
// do nothing
|
// do nothing
|
||||||
@@ -346,41 +357,41 @@ extern "C" void cospike_cosim(long long int cycle,
|
|||||||
} else if (debug_interrupt) {
|
} else if (debug_interrupt) {
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
printf("Unknown interrupt %lx\n", interrupt_cause);
|
COSPIKE_PRINTF("Unknown interrupt %lx\n", interrupt_cause);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (raise_exception)
|
if (raise_exception)
|
||||||
printf("%d exception %lx\n", cycle, cause);
|
COSPIKE_PRINTF("%d exception %lx\n", cycle, cause);
|
||||||
if (valid) {
|
if (valid) {
|
||||||
p->clear_waiting_for_interrupt();
|
p->clear_waiting_for_interrupt();
|
||||||
printf("%d Cosim: %lx", cycle, iaddr);
|
COSPIKE_PRINTF("%d Cosim: %lx", cycle, iaddr);
|
||||||
// if (has_wdata) {
|
// if (has_wdata) {
|
||||||
// printf(" s: %lx", wdata);
|
// COSPIKE_PRINTF(" s: %lx", wdata);
|
||||||
// }
|
// }
|
||||||
printf("\n");
|
COSPIKE_PRINTF("\n");
|
||||||
}
|
}
|
||||||
if (valid || raise_interrupt || raise_exception) {
|
if (valid || raise_interrupt || raise_exception) {
|
||||||
p->clear_waiting_for_interrupt();
|
p->clear_waiting_for_interrupt();
|
||||||
for (auto& e : read_override_devices) e->was_read_from = false;
|
for (auto& e : read_override_devices) e.get()->was_read_from = false;
|
||||||
p->step(1);
|
p->step(1);
|
||||||
if (unlikely(cospike_debug)) {
|
if (unlikely(cospike_debug)) {
|
||||||
printf("spike pc is %lx\n", s->pc);
|
COSPIKE_PRINTF("spike pc is %lx\n", s->pc);
|
||||||
printf("spike mstatus is %lx\n", s->mstatus->read());
|
COSPIKE_PRINTF("spike mstatus is %lx\n", s->mstatus->read());
|
||||||
printf("spike mip is %lx\n", s->mip->read());
|
COSPIKE_PRINTF("spike mip is %lx\n", s->mip->read());
|
||||||
printf("spike mie is %lx\n", s->mie->read());
|
COSPIKE_PRINTF("spike mie is %lx\n", s->mie->read());
|
||||||
printf("spike wfi state is %d\n", p->is_waiting_for_interrupt());
|
COSPIKE_PRINTF("spike wfi state is %d\n", p->is_waiting_for_interrupt());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (valid && !raise_exception) {
|
if (valid && !raise_exception) {
|
||||||
if (s_pc != iaddr) {
|
if (s_pc != iaddr) {
|
||||||
printf("%d PC mismatch spike %llx != DUT %llx\n", cycle, s_pc, iaddr);
|
COSPIKE_PRINTF("%d PC mismatch spike %llx != DUT %llx\n", cycle, s_pc, iaddr);
|
||||||
if (unlikely(cospike_debug)) {
|
if (unlikely(cospike_debug)) {
|
||||||
printf("spike mstatus is %lx\n", s->mstatus->read());
|
COSPIKE_PRINTF("spike mstatus is %lx\n", s->mstatus->read());
|
||||||
printf("spike mcause is %lx\n", s->mcause->read());
|
COSPIKE_PRINTF("spike mcause is %lx\n", s->mcause->read());
|
||||||
printf("spike mtval is %lx\n" , s->mtval->read());
|
COSPIKE_PRINTF("spike mtval is %lx\n" , s->mtval->read());
|
||||||
printf("spike mtinst is %lx\n", s->mtinst->read());
|
COSPIKE_PRINTF("spike mtinst is %lx\n", s->mtinst->read());
|
||||||
}
|
}
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@@ -401,7 +412,7 @@ extern "C" void cospike_cosim(long long int cycle,
|
|||||||
}
|
}
|
||||||
// Try to remember magic_mem addrs, and ignore these in the future
|
// Try to remember magic_mem addrs, and ignore these in the future
|
||||||
if ( waddr == tohost_addr && w_data >= info->mem0_base && w_data < (info->mem0_base + info->mem0_size)) {
|
if ( waddr == tohost_addr && w_data >= info->mem0_base && w_data < (info->mem0_base + info->mem0_size)) {
|
||||||
printf("Probable magic mem %lx\n", w_data);
|
COSPIKE_PRINTF("Probable magic mem %lx\n", w_data);
|
||||||
magic_addrs.insert(w_data);
|
magic_addrs.insert(w_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -424,7 +435,7 @@ extern "C" void cospike_cosim(long long int cycle,
|
|||||||
// 3 => vec hint
|
// 3 => vec hint
|
||||||
// 4 => csr
|
// 4 => csr
|
||||||
bool device_read = false;
|
bool device_read = false;
|
||||||
for (auto& e : read_override_devices) if (e->was_read_from) device_read = true;
|
for (auto& e : read_override_devices) if (e.get()->was_read_from) device_read = true;
|
||||||
|
|
||||||
bool lr_read = ((insn & MASK_LR_D) == MATCH_LR_D) || ((insn & MASK_LR_W) == MATCH_LR_W);
|
bool lr_read = ((insn & MASK_LR_D) == MATCH_LR_D) || ((insn & MASK_LR_W) == MATCH_LR_W);
|
||||||
bool sc_read = ((insn & MASK_SC_D) == MATCH_SC_D) || ((insn & MASK_SC_W) == MATCH_SC_W);
|
bool sc_read = ((insn & MASK_SC_D) == MATCH_SC_D) || ((insn & MASK_SC_W) == MATCH_SC_W);
|
||||||
@@ -449,7 +460,7 @@ extern "C" void cospike_cosim(long long int cycle,
|
|||||||
uint64_t csr_addr = (insn >> 20) & 0xfff;
|
uint64_t csr_addr = (insn >> 20) & 0xfff;
|
||||||
bool csr_read = (insn & 0x7f) == 0x73;
|
bool csr_read = (insn & 0x7f) == 0x73;
|
||||||
if (csr_read)
|
if (csr_read)
|
||||||
printf("CSR read %lx\n", csr_addr);
|
COSPIKE_PRINTF("CSR read %lx\n", csr_addr);
|
||||||
if (csr_read && ((csr_addr == 0x301) || // misa
|
if (csr_read && ((csr_addr == 0x301) || // misa
|
||||||
(csr_addr == 0x306) || // mcounteren
|
(csr_addr == 0x306) || // mcounteren
|
||||||
(csr_addr == 0xf13) || // mimpid
|
(csr_addr == 0xf13) || // mimpid
|
||||||
@@ -463,17 +474,17 @@ extern "C" void cospike_cosim(long long int cycle,
|
|||||||
(csr_addr >= 0x7a0 && csr_addr <= 0x7aa) || // debug trigger registers
|
(csr_addr >= 0x7a0 && csr_addr <= 0x7aa) || // debug trigger registers
|
||||||
(csr_addr >= 0x3b0 && csr_addr <= 0x3ef) // pmpaddr
|
(csr_addr >= 0x3b0 && csr_addr <= 0x3ef) // pmpaddr
|
||||||
)) {
|
)) {
|
||||||
printf("CSR override\n");
|
COSPIKE_PRINTF("CSR override\n");
|
||||||
s->XPR.write(rd, wdata);
|
s->XPR.write(rd, wdata);
|
||||||
} else if (ignore_read) {
|
} else if (ignore_read) {
|
||||||
// Don't check reads from tohost, reads from magic memory, or reads
|
// Don't check reads from tohost, reads from magic memory, or reads
|
||||||
// from clint Technically this could be buggy because log_mem_read
|
// from clint Technically this could be buggy because log_mem_read
|
||||||
// only reports vaddrs, but no software ever should access
|
// only reports vaddrs, but no software ever should access
|
||||||
// tohost/fromhost/clint with vaddrs anyways
|
// tohost/fromhost/clint with vaddrs anyways
|
||||||
printf("Read override %lx = %lx\n", mem_read_addr, wdata);
|
COSPIKE_PRINTF("Read override %lx = %lx\n", mem_read_addr, wdata);
|
||||||
s->XPR.write(rd, wdata);
|
s->XPR.write(rd, wdata);
|
||||||
} else if (wdata != regwrite.second.v[0]) {
|
} else if (wdata != regwrite.second.v[0]) {
|
||||||
printf("%d wdata mismatch reg %d %lx != %lx\n", cycle, rd,
|
COSPIKE_PRINTF("%d wdata mismatch reg %d %lx != %lx\n", cycle, rd,
|
||||||
regwrite.second.v[0], wdata);
|
regwrite.second.v[0], wdata);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@@ -481,7 +492,7 @@ extern "C" void cospike_cosim(long long int cycle,
|
|||||||
|
|
||||||
// TODO FIX: Rocketchip TracedInstruction.wdata should be Valid(UInt)
|
// TODO FIX: Rocketchip TracedInstruction.wdata should be Valid(UInt)
|
||||||
// if (scalar_wb ^ has_wdata) {
|
// if (scalar_wb ^ has_wdata) {
|
||||||
// printf("Scalar wdata behavior divergence between spike and DUT\n");
|
// COSPIKE_PRINTF("Scalar wdata behavior divergence between spike and DUT\n");
|
||||||
// exit(-1);
|
// exit(-1);
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import "DPI-C" function void cospike_set_sysinfo(
|
import "DPI-C" function void cospike_set_sysinfo(
|
||||||
input string isa,
|
input string isa,
|
||||||
|
input string priv,
|
||||||
input int pmpregions,
|
input int pmpregions,
|
||||||
input longint mem0_base,
|
input longint mem0_base,
|
||||||
input longint mem0_size,
|
input longint mem0_size,
|
||||||
@@ -23,6 +24,7 @@ import "DPI-C" function void cospike_cosim(input longint cycle,
|
|||||||
|
|
||||||
module SpikeCosim #(
|
module SpikeCosim #(
|
||||||
parameter ISA,
|
parameter ISA,
|
||||||
|
parameter PRIV,
|
||||||
parameter PMPREGIONS,
|
parameter PMPREGIONS,
|
||||||
parameter MEM0_BASE,
|
parameter MEM0_BASE,
|
||||||
parameter MEM0_SIZE,
|
parameter MEM0_SIZE,
|
||||||
@@ -57,7 +59,7 @@ module SpikeCosim #(
|
|||||||
);
|
);
|
||||||
|
|
||||||
initial begin
|
initial begin
|
||||||
cospike_set_sysinfo(ISA, PMPREGIONS, MEM0_BASE, MEM0_SIZE, NHARTS, BOOTROM);
|
cospike_set_sysinfo(ISA, PRIV, PMPREGIONS, MEM0_BASE, MEM0_SIZE, NHARTS, BOOTROM);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
always @(posedge clock) begin
|
always @(posedge clock) begin
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import testchipip.TileTraceIO
|
|||||||
|
|
||||||
case class SpikeCosimConfig(
|
case class SpikeCosimConfig(
|
||||||
isa: String,
|
isa: String,
|
||||||
|
priv: String,
|
||||||
pmpregions: Int,
|
pmpregions: Int,
|
||||||
mem0_base: BigInt,
|
mem0_base: BigInt,
|
||||||
mem0_size: BigInt,
|
mem0_size: BigInt,
|
||||||
@@ -24,6 +25,7 @@ case class SpikeCosimConfig(
|
|||||||
|
|
||||||
class SpikeCosim(cfg: SpikeCosimConfig) extends BlackBox(Map(
|
class SpikeCosim(cfg: SpikeCosimConfig) extends BlackBox(Map(
|
||||||
"ISA" -> StringParam(cfg.isa),
|
"ISA" -> StringParam(cfg.isa),
|
||||||
|
"PRIV" -> StringParam(cfg.priv),
|
||||||
"PMPREGIONS" -> IntParam(cfg.pmpregions),
|
"PMPREGIONS" -> IntParam(cfg.pmpregions),
|
||||||
"MEM0_BASE" -> IntParam(cfg.mem0_base),
|
"MEM0_BASE" -> IntParam(cfg.mem0_base),
|
||||||
"MEM0_SIZE" -> IntParam(cfg.mem0_size),
|
"MEM0_SIZE" -> IntParam(cfg.mem0_size),
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ import chisel3.util.{log2Up}
|
|||||||
|
|
||||||
import org.chipsalliance.cde.config.{Config}
|
import org.chipsalliance.cde.config.{Config}
|
||||||
import freechips.rocketchip.devices.tilelink.{BootROMLocated, PLICKey, CLINTKey}
|
import freechips.rocketchip.devices.tilelink.{BootROMLocated, PLICKey, CLINTKey}
|
||||||
import freechips.rocketchip.devices.debug.{Debug, ExportDebug, DebugModuleKey, DMI}
|
import freechips.rocketchip.devices.debug.{Debug, ExportDebug, DebugModuleKey, DMI, JtagDTMKey, JtagDTMConfig}
|
||||||
|
import freechips.rocketchip.diplomacy.{AsynchronousCrossing}
|
||||||
import freechips.rocketchip.stage.phases.TargetDirKey
|
import freechips.rocketchip.stage.phases.TargetDirKey
|
||||||
import freechips.rocketchip.subsystem._
|
import freechips.rocketchip.subsystem._
|
||||||
import freechips.rocketchip.tile.{XLen}
|
import freechips.rocketchip.tile.{XLen}
|
||||||
@@ -14,49 +15,125 @@ import freechips.rocketchip.tile.{XLen}
|
|||||||
import sifive.blocks.devices.gpio._
|
import sifive.blocks.devices.gpio._
|
||||||
import sifive.blocks.devices.uart._
|
import sifive.blocks.devices.uart._
|
||||||
import sifive.blocks.devices.spi._
|
import sifive.blocks.devices.spi._
|
||||||
|
import sifive.blocks.devices.i2c._
|
||||||
|
|
||||||
import testchipip._
|
import testchipip._
|
||||||
|
|
||||||
import chipyard.{ExtTLMem}
|
import chipyard.{ExtTLMem}
|
||||||
|
|
||||||
// Set the bootrom to the Chipyard bootrom
|
/**
|
||||||
class WithBootROM extends Config((site, here, up) => {
|
* Config fragment for adding a BootROM to the SoC
|
||||||
|
*
|
||||||
|
* @param address the address of the BootROM device
|
||||||
|
* @param size the size of the BootROM
|
||||||
|
* @param hang the power-on reset vector, i.e. the program counter will be set to this value on reset
|
||||||
|
* @param contentFileName the path to the BootROM image
|
||||||
|
*/
|
||||||
|
class WithBootROM(address: BigInt = 0x10000, size: Int = 0x10000, hang: BigInt = 0x10040) extends Config((site, here, up) => {
|
||||||
case BootROMLocated(x) => up(BootROMLocated(x), site)
|
case BootROMLocated(x) => up(BootROMLocated(x), site)
|
||||||
.map(_.copy(contentFileName = s"${site(TargetDirKey)}/bootrom.rv${site(XLen)}.img"))
|
.map(_.copy(
|
||||||
|
address = address,
|
||||||
|
size = size,
|
||||||
|
hang = hang,
|
||||||
|
contentFileName = s"${site(TargetDirKey)}/bootrom.rv${site(XLen)}.img"
|
||||||
|
))
|
||||||
})
|
})
|
||||||
|
|
||||||
// DOC include start: gpio config fragment
|
// DOC include start: gpio config fragment
|
||||||
class WithGPIO extends Config((site, here, up) => {
|
/**
|
||||||
case PeripheryGPIOKey => Seq(
|
* Config fragment for adding a GPIO peripheral device to the SoC
|
||||||
GPIOParams(address = 0x10012000, width = 4, includeIOF = false))
|
*
|
||||||
|
* @param address the address of the GPIO device
|
||||||
|
* @param width the number of pins of the GPIO device
|
||||||
|
*/
|
||||||
|
class WithGPIO(address: BigInt = 0x10010000, width: Int = 4) extends Config ((site, here, up) => {
|
||||||
|
case PeripheryGPIOKey => up(PeripheryGPIOKey) ++ Seq(
|
||||||
|
GPIOParams(address = address, width = width, includeIOF = false))
|
||||||
})
|
})
|
||||||
// DOC include end: gpio config fragment
|
// DOC include end: gpio config fragment
|
||||||
|
|
||||||
class WithUART(baudrate: BigInt = 115200) extends Config((site, here, up) => {
|
/**
|
||||||
case PeripheryUARTKey => Seq(
|
* Config fragment for removing all UART peripheral devices from the SoC
|
||||||
UARTParams(address = 0x54000000L, nTxEntries = 256, nRxEntries = 256, initBaudRate = baudrate))
|
*/
|
||||||
})
|
|
||||||
|
|
||||||
class WithNoUART extends Config((site, here, up) => {
|
class WithNoUART extends Config((site, here, up) => {
|
||||||
case PeripheryUARTKey => Nil
|
case PeripheryUARTKey => Nil
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Config fragment for adding a UART peripheral device to the SoC
|
||||||
|
*
|
||||||
|
* @param address the address of the UART device
|
||||||
|
* @param baudrate the baudrate of the UART device
|
||||||
|
*/
|
||||||
|
class WithUART(baudrate: BigInt = 115200, address: BigInt = 0x10020000) extends Config ((site, here, up) => {
|
||||||
|
case PeripheryUARTKey => up(PeripheryUARTKey) ++ Seq(
|
||||||
|
UARTParams(address = address, nTxEntries = 256, nRxEntries = 256, initBaudRate = baudrate))
|
||||||
|
})
|
||||||
|
|
||||||
class WithUARTFIFOEntries(txEntries: Int, rxEntries: Int) extends Config((site, here, up) => {
|
class WithUARTFIFOEntries(txEntries: Int, rxEntries: Int) extends Config((site, here, up) => {
|
||||||
case PeripheryUARTKey => up(PeripheryUARTKey).map(_.copy(nTxEntries = txEntries, nRxEntries = rxEntries))
|
case PeripheryUARTKey => up(PeripheryUARTKey).map(_.copy(nTxEntries = txEntries, nRxEntries = rxEntries))
|
||||||
})
|
})
|
||||||
|
|
||||||
class WithSPIFlash(size: BigInt = 0x10000000) extends Config((site, here, up) => {
|
class WithUARTInitBaudRate(baudrate: BigInt = 115200) extends Config ((site, here, up) => {
|
||||||
|
case PeripheryUARTKey => up(PeripheryUARTKey).map(_.copy(initBaudRate=baudrate))
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Config fragment for adding a SPI peripheral device with Execute-in-Place capability to the SoC
|
||||||
|
*
|
||||||
|
* @param address the address of the SPI controller
|
||||||
|
* @param fAddress the address of the Execute-in-Place (XIP) region of the SPI flash memory
|
||||||
|
* @param size the size of the Execute-in-Place (XIP) region of the SPI flash memory
|
||||||
|
*/
|
||||||
|
class WithSPIFlash(size: BigInt = 0x10000000, address: BigInt = 0x10030000, fAddress: BigInt = 0x20000000) extends Config((site, here, up) => {
|
||||||
// Note: the default size matches freedom with the addresses below
|
// Note: the default size matches freedom with the addresses below
|
||||||
case PeripherySPIFlashKey => Seq(
|
case PeripherySPIFlashKey => up(PeripherySPIFlashKey) ++ Seq(
|
||||||
SPIFlashParams(rAddress = 0x10040000, fAddress = 0x20000000, fSize = size))
|
SPIFlashParams(rAddress = address, fAddress = fAddress, fSize = size))
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Config fragment for adding a SPI peripheral device to the SoC
|
||||||
|
*
|
||||||
|
* @param address the address of the SPI controller
|
||||||
|
*/
|
||||||
|
class WithSPI(address: BigInt = 0x10031000) extends Config((site, here, up) => {
|
||||||
|
case PeripherySPIKey => up(PeripherySPIKey) ++ Seq(
|
||||||
|
SPIParams(rAddress = address))
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Config fragment for adding a I2C peripheral device to the SoC
|
||||||
|
*
|
||||||
|
* @param address the address of the I2C controller
|
||||||
|
*/
|
||||||
|
class WithI2C(address: BigInt = 0x10040000) extends Config((site, here, up) => {
|
||||||
|
case PeripheryI2CKey => up(PeripheryI2CKey) ++ Seq(
|
||||||
|
I2CParams(address = address, controlXType = AsynchronousCrossing(), intXType = AsynchronousCrossing())
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
class WithNoDebug extends Config((site, here, up) => {
|
||||||
|
case DebugModuleKey => None
|
||||||
})
|
})
|
||||||
|
|
||||||
class WithDMIDTM extends Config((site, here, up) => {
|
class WithDMIDTM extends Config((site, here, up) => {
|
||||||
case ExportDebug => up(ExportDebug, site).copy(protocols = Set(DMI))
|
case ExportDebug => up(ExportDebug, site).copy(protocols = Set(DMI))
|
||||||
})
|
})
|
||||||
|
|
||||||
class WithNoDebug extends Config((site, here, up) => {
|
/**
|
||||||
case DebugModuleKey => None
|
* Config fragment for adding a JTAG Debug Module to the SoC
|
||||||
|
*
|
||||||
|
* @param idcodeVersion the version of the JTAG protocol the Debug Module supports
|
||||||
|
* @param partNum the part number of the Debug Module
|
||||||
|
* @param manufId the 11-bit JEDEC Designer ID of the chip manufacturer
|
||||||
|
* @param debugIdleCycles the number of cycles the Debug Module waits before responding to a request
|
||||||
|
*/
|
||||||
|
class WithJTAGDTMKey(idcodeVersion: Int = 2, partNum: Int = 0x000, manufId: Int = 0x489, debugIdleCycles: Int = 5) extends Config((site, here, up) => {
|
||||||
|
case JtagDTMKey => new JtagDTMConfig (
|
||||||
|
idcodeVersion = idcodeVersion,
|
||||||
|
idcodePartNum = partNum,
|
||||||
|
idcodeManufId = manufId,
|
||||||
|
debugIdleCycles = debugIdleCycles)
|
||||||
})
|
})
|
||||||
|
|
||||||
class WithTLBackingMemory extends Config((site, here, up) => {
|
class WithTLBackingMemory extends Config((site, here, up) => {
|
||||||
|
|||||||
@@ -365,6 +365,7 @@ class WithCospike extends ComposeHarnessBinder({
|
|||||||
val tiles = chipyardSystem.tiles
|
val tiles = chipyardSystem.tiles
|
||||||
val cfg = SpikeCosimConfig(
|
val cfg = SpikeCosimConfig(
|
||||||
isa = tiles.headOption.map(_.isaDTS).getOrElse(""),
|
isa = tiles.headOption.map(_.isaDTS).getOrElse(""),
|
||||||
|
priv = tiles.headOption.map(t => if (t.usingUser) "MSU" else if (t.usingSupervisor) "MS" else "M").getOrElse(""),
|
||||||
mem0_base = p(ExtMem).map(_.master.base).getOrElse(BigInt(0)),
|
mem0_base = p(ExtMem).map(_.master.base).getOrElse(BigInt(0)),
|
||||||
mem0_size = p(ExtMem).map(_.master.size).getOrElse(BigInt(0)),
|
mem0_size = p(ExtMem).map(_.master.size).getOrElse(BigInt(0)),
|
||||||
pmpregions = tiles.headOption.map(_.tileParams.core.nPMPs).getOrElse(0),
|
pmpregions = tiles.headOption.map(_.tileParams.core.nPMPs).getOrElse(0),
|
||||||
|
|||||||
@@ -34,5 +34,5 @@ class TestHarness(implicit val p: Parameters) extends Module with HasHarnessInst
|
|||||||
def referenceClock = clock
|
def referenceClock = clock
|
||||||
def referenceReset = reset
|
def referenceReset = reset
|
||||||
|
|
||||||
instantiateChipTops()
|
val lazyDuts = instantiateChipTops()
|
||||||
}
|
}
|
||||||
|
|||||||
90
generators/chipyard/src/main/scala/upf/ChipTopUPF.scala
Normal file
90
generators/chipyard/src/main/scala/upf/ChipTopUPF.scala
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
// See LICENSE for license details
|
||||||
|
package chipyard.upf
|
||||||
|
|
||||||
|
import scala.collection.mutable.{ListBuffer}
|
||||||
|
import scalax.collection.mutable.{Graph}
|
||||||
|
import scalax.collection.GraphPredef._, scalax.collection.GraphEdge._
|
||||||
|
|
||||||
|
import chipyard.harness.{TestHarness}
|
||||||
|
import freechips.rocketchip.diplomacy.{LazyModule}
|
||||||
|
|
||||||
|
object ChipTopUPF {
|
||||||
|
|
||||||
|
def default: UPFFunc.UPFFunction = {
|
||||||
|
case top: LazyModule => {
|
||||||
|
val modulesList = getLazyModules(top)
|
||||||
|
val pdList = createPowerDomains(modulesList)
|
||||||
|
val g = connectPDHierarchy(pdList)
|
||||||
|
traverseGraph(g, UPFGenerator.generateUPF)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def getLazyModules(top: LazyModule): ListBuffer[LazyModule] = {
|
||||||
|
var i = 0
|
||||||
|
var result = new ListBuffer[LazyModule]()
|
||||||
|
result.append(top)
|
||||||
|
while (i < result.length) {
|
||||||
|
val lazyMod = result(i)
|
||||||
|
for (child <- lazyMod.getChildren) {
|
||||||
|
result.append(child)
|
||||||
|
}
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
def createPowerDomains(modulesList: ListBuffer[LazyModule]): ListBuffer[PowerDomain] = {
|
||||||
|
var pdList = ListBuffer[PowerDomain]()
|
||||||
|
for (pdInput <- UPFInputs.upfInfo) {
|
||||||
|
val pd = new PowerDomain(name=pdInput.name, modules=getPDModules(pdInput, modulesList),
|
||||||
|
isTop=pdInput.isTop, isGated=pdInput.isGated,
|
||||||
|
highVoltage=pdInput.highVoltage, lowVoltage=pdInput.lowVoltage)
|
||||||
|
pdList.append(pd)
|
||||||
|
}
|
||||||
|
return pdList
|
||||||
|
}
|
||||||
|
|
||||||
|
def getPDModules(pdInput: PowerDomainInput, modulesList: ListBuffer[LazyModule]): ListBuffer[LazyModule] = {
|
||||||
|
var pdModules = ListBuffer[LazyModule]()
|
||||||
|
for (moduleName <- pdInput.moduleList) {
|
||||||
|
var module = modulesList.filter(_.module.name == moduleName)
|
||||||
|
if (module.length == 1) { // filter returns a collection
|
||||||
|
pdModules.append(module(0))
|
||||||
|
} else {
|
||||||
|
module = modulesList.filter(_.module.instanceName == moduleName)
|
||||||
|
if (module.length == 1) {
|
||||||
|
pdModules.append(module(0))
|
||||||
|
} else {
|
||||||
|
module = modulesList.filter(_.module.pathName == moduleName)
|
||||||
|
if (module.length == 1) {
|
||||||
|
pdModules.append(module(0))
|
||||||
|
} else {
|
||||||
|
throw new Exception(s"PowerDomainInput module list doesn't exist in design.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pdModules
|
||||||
|
}
|
||||||
|
|
||||||
|
def connectPDHierarchy(pdList: ListBuffer[PowerDomain]): Graph[PowerDomain, DiEdge] = {
|
||||||
|
var g = Graph[PowerDomain, DiEdge]()
|
||||||
|
for (pd <- pdList) {
|
||||||
|
val pdInput = UPFInputs.upfInfo.filter(_.name == pd.name)(0)
|
||||||
|
val childPDs = pdList.filter(x => pdInput.childrenPDs.contains(x.name))
|
||||||
|
for (childPD <- childPDs) {
|
||||||
|
g += (pd ~> childPD) // directed edge from pd to childPD
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return g
|
||||||
|
}
|
||||||
|
|
||||||
|
def traverseGraph(g: Graph[PowerDomain, DiEdge], action: (PowerDomain, Graph[PowerDomain, DiEdge]) => Unit): Unit = {
|
||||||
|
for (node <- g.nodes.filter(_.diPredecessors.isEmpty)) { // all nodes without parents
|
||||||
|
g.outerNodeTraverser(node).foreach(pd => action(pd, g))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
case object ChipTopUPFAspect extends UPFAspect[chipyard.harness.TestHarness](ChipTopUPF.default)
|
||||||
24
generators/chipyard/src/main/scala/upf/UPFAspect.scala
Normal file
24
generators/chipyard/src/main/scala/upf/UPFAspect.scala
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
// See LICENSE for license details
|
||||||
|
package chipyard.upf
|
||||||
|
|
||||||
|
import chisel3.aop.{Aspect}
|
||||||
|
import firrtl.{AnnotationSeq}
|
||||||
|
import chipyard.harness.{TestHarness}
|
||||||
|
import freechips.rocketchip.stage.phases.{TargetDirKey}
|
||||||
|
import freechips.rocketchip.diplomacy.{LazyModule}
|
||||||
|
|
||||||
|
abstract class UPFAspect[T <: TestHarness](upf: UPFFunc.UPFFunction) extends Aspect[T] {
|
||||||
|
|
||||||
|
final override def toAnnotation(top: T): AnnotationSeq = {
|
||||||
|
UPFFunc.UPFPath = top.p(TargetDirKey) + "/upf"
|
||||||
|
require(top.lazyDuts.length == 1) // currently only supports 1 chiptop
|
||||||
|
upf(top.lazyDuts.head)
|
||||||
|
AnnotationSeq(Seq()) // noop
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
object UPFFunc {
|
||||||
|
type UPFFunction = PartialFunction[LazyModule, Unit]
|
||||||
|
var UPFPath = "" // output dir path
|
||||||
|
}
|
||||||
264
generators/chipyard/src/main/scala/upf/UPFGen.scala
Normal file
264
generators/chipyard/src/main/scala/upf/UPFGen.scala
Normal file
@@ -0,0 +1,264 @@
|
|||||||
|
// See LICENSE for license details
|
||||||
|
package chipyard.upf
|
||||||
|
|
||||||
|
import java.io.{FileWriter}
|
||||||
|
import java.nio.file.{Paths, Files}
|
||||||
|
import scala.collection.mutable.{ListBuffer}
|
||||||
|
import scalax.collection.mutable.{Graph}
|
||||||
|
import scalax.collection.GraphPredef._, scalax.collection.GraphEdge._
|
||||||
|
|
||||||
|
import freechips.rocketchip.diplomacy.{LazyModule}
|
||||||
|
|
||||||
|
case class PowerDomain (val name: String, val modules: ListBuffer[LazyModule],
|
||||||
|
val isTop: Boolean, val isGated: Boolean,
|
||||||
|
val highVoltage: Double, val lowVoltage: Double) {
|
||||||
|
val mainVoltage = isGated match {
|
||||||
|
case true => highVoltage // gated nets should have access to high voltage rail (since they are being gated to optimize power)
|
||||||
|
case false => lowVoltage // currently assuming non-gated nets are on low voltage rail
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object UPFGenerator {
|
||||||
|
|
||||||
|
def generateUPF(pd: PowerDomain, g: Graph[PowerDomain, DiEdge]): Unit = {
|
||||||
|
val node = g.get(pd)
|
||||||
|
val children = node.diSuccessors.map(x => x.toOuter).toList
|
||||||
|
val pdList = g.nodes.map(x => x.toOuter).toList
|
||||||
|
val filePath = UPFFunc.UPFPath
|
||||||
|
val fileName = s"${pd.name}.upf"
|
||||||
|
writeFile(filePath, fileName, createMessage(pd, children, pdList))
|
||||||
|
}
|
||||||
|
|
||||||
|
def createMessage(pd: PowerDomain, children: List[PowerDomain], pdList: List[PowerDomain]): String = {
|
||||||
|
var message = ""
|
||||||
|
message += loadUPF(pd, children)
|
||||||
|
message += createPowerDomains(pd)
|
||||||
|
message += createSupplyPorts(pd)
|
||||||
|
message += createSupplyNets(pd)
|
||||||
|
message += connectSupplies(pd)
|
||||||
|
message += setDomainNets(pd)
|
||||||
|
message += createPowerSwitches(pd)
|
||||||
|
message += createPowerStateTable(pd, getPorts(pd, children))
|
||||||
|
message += createLevelShifters(pd, pdList)
|
||||||
|
return message
|
||||||
|
}
|
||||||
|
|
||||||
|
def writeFile(filePath: String, fileName: String, message: String): Unit = {
|
||||||
|
if (!Files.exists(Paths.get(filePath))) {
|
||||||
|
Files.createDirectories(Paths.get(filePath))
|
||||||
|
}
|
||||||
|
val fw = new FileWriter(s"${filePath}/${fileName}", false)
|
||||||
|
fw.write(message)
|
||||||
|
fw.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
def getPorts(pd: PowerDomain, children: List[PowerDomain]): ListBuffer[String] = {
|
||||||
|
var portsList = ListBuffer[String]()
|
||||||
|
portsList += "VDDH"
|
||||||
|
portsList += "VDDL"
|
||||||
|
if (pd.isGated) {
|
||||||
|
portsList += s"VDD_${pd.name}"
|
||||||
|
}
|
||||||
|
for (child <- children) {
|
||||||
|
if (child.isGated) {
|
||||||
|
portsList += s"VDD_${child.name}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return portsList
|
||||||
|
}
|
||||||
|
|
||||||
|
def loadUPF(pd: PowerDomain, children: List[PowerDomain]): String = {
|
||||||
|
var message = "##### Set Scope and Load UPF #####\n"
|
||||||
|
var subMessage = s"set_scope /${pd.modules(0).module.name}\n" //
|
||||||
|
children.foreach{
|
||||||
|
child => {
|
||||||
|
subMessage += s"load_upf ${child.name}.upf -scope ${child.modules(0).module.name}\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
message += subMessage
|
||||||
|
message += "\n"
|
||||||
|
return message
|
||||||
|
}
|
||||||
|
|
||||||
|
def createPowerDomains(pd: PowerDomain): String = {
|
||||||
|
var message = "##### Create Power Domains #####\n"
|
||||||
|
var subMessage = ""
|
||||||
|
pd.isTop match {
|
||||||
|
case true => subMessage += s"create_power_domain ${pd.name} -include_scope\n"
|
||||||
|
case false => {
|
||||||
|
subMessage += s"create_power_domain ${pd.name} -elements { "
|
||||||
|
for (module <- pd.modules) {
|
||||||
|
subMessage += s"${module.module.name} "
|
||||||
|
}
|
||||||
|
subMessage += "}\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
message += subMessage
|
||||||
|
message += "\n"
|
||||||
|
return message
|
||||||
|
}
|
||||||
|
|
||||||
|
def createSupplyPorts(pd: PowerDomain): String = {
|
||||||
|
if (!pd.isTop) {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
var message = "##### Create Supply Ports #####\n"
|
||||||
|
var subMessage = pd.isTop match {
|
||||||
|
case true => {
|
||||||
|
s"create_supply_port VDDH -direction in -domain ${pd.name}\n" +
|
||||||
|
s"create_supply_port VDDL -direction in -domain ${pd.name}\n" +
|
||||||
|
s"create_supply_port VSS -direction in -domain ${pd.name}\n"
|
||||||
|
}
|
||||||
|
case false => ""
|
||||||
|
}
|
||||||
|
message += subMessage
|
||||||
|
message += "\n"
|
||||||
|
return message
|
||||||
|
}
|
||||||
|
|
||||||
|
def createSupplyNets(pd: PowerDomain): String = {
|
||||||
|
var message = "##### Create Supply Nets #####\n"
|
||||||
|
var subMessage = pd.isTop match {
|
||||||
|
case true => {
|
||||||
|
s"create_supply_net VDDH -domain ${pd.name}\n" +
|
||||||
|
s"create_supply_net VDDL -domain ${pd.name}\n" +
|
||||||
|
s"create_supply_net VSS -domain ${pd.name}\n"
|
||||||
|
}
|
||||||
|
case false => {
|
||||||
|
s"create_supply_net VDDH -domain ${pd.name} -reuse\n" +
|
||||||
|
s"create_supply_net VDDL -domain ${pd.name} -reuse\n" +
|
||||||
|
s"create_supply_net VSS -domain ${pd.name} -reuse\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pd.isGated) {
|
||||||
|
subMessage += s"create_supply_net VDD_${pd.name} -domain ${pd.name}\n"
|
||||||
|
}
|
||||||
|
message += subMessage
|
||||||
|
message += "\n"
|
||||||
|
return message
|
||||||
|
}
|
||||||
|
|
||||||
|
def connectSupplies(pd: PowerDomain): String = {
|
||||||
|
var message = "##### Connect Supply Nets and Ports #####\n"
|
||||||
|
var subMessage = "connect_supply_net VDDH -ports VDDH\n" +
|
||||||
|
"connect_supply_net VDDL -ports VDDL\n" +
|
||||||
|
"connect_supply_net VSS -ports VSS\n"
|
||||||
|
message += subMessage
|
||||||
|
message += "\n"
|
||||||
|
return message
|
||||||
|
}
|
||||||
|
|
||||||
|
def setDomainNets(pd: PowerDomain): String = {
|
||||||
|
var message = "##### Set Domain Supply Nets #####\n"
|
||||||
|
var subMessage = pd.isGated match {
|
||||||
|
case true => s"set_domain_supply_net ${pd.name} -primary_power_net VDD_${pd.name} -primary_ground_net VSS\n"
|
||||||
|
case false => s"set_domain_supply_net ${pd.name} -primary_power_net VDDL -primary_ground_net VSS\n"
|
||||||
|
}
|
||||||
|
message += subMessage
|
||||||
|
message += "\n"
|
||||||
|
return message
|
||||||
|
}
|
||||||
|
|
||||||
|
def createPowerSwitches(pd: PowerDomain): String = {
|
||||||
|
if (!pd.isGated) {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
var message = "##### Power Switches #####\n"
|
||||||
|
var subMessage = pd.isGated match {
|
||||||
|
case true => s"""create_power_switch sw_${pd.name} -domain ${pd.name} -input_supply_port "psw_VDDH VDDH" """ +
|
||||||
|
s"""-output_supply_port "psw_VDD_${pd.name} VDD_${pd.name}" """ +
|
||||||
|
s"""-control_port "psw_${pd.name}_en ${pd.modules(0).module.name}/${pd.modules(0).module.name}_en" """ +
|
||||||
|
s"""-on_state "psw_${pd.name}_ON psw_VDDH { !psw_${pd.name}_en }"""" + "\n"
|
||||||
|
case false => ""
|
||||||
|
}
|
||||||
|
message += subMessage
|
||||||
|
message += "\n"
|
||||||
|
return message
|
||||||
|
}
|
||||||
|
|
||||||
|
def createPowerStateTable(pd: PowerDomain, portsList: ListBuffer[String]): String = {
|
||||||
|
if (!pd.isTop) {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
var message = "##### Power State Table #####\n"
|
||||||
|
var portStates = ""
|
||||||
|
var createPST = "create_pst pst_table -supplies { "
|
||||||
|
|
||||||
|
for (port <- portsList) {
|
||||||
|
createPST += s"${port} "
|
||||||
|
if (port == "VDDH") {
|
||||||
|
portStates += s"add_port_state ${port} -state { HighVoltage ${pd.highVoltage} }\n"
|
||||||
|
} else if (port == "VDDL") {
|
||||||
|
portStates += s"add_port_state ${port} -state { LowVoltage ${pd.lowVoltage} }\n"
|
||||||
|
} else { // gated
|
||||||
|
portStates += s"add_port_state ${port} -state { HighVoltage ${pd.highVoltage } -state { ${port}_OFF off }\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
portStates += "\n"
|
||||||
|
createPST += "}\n\n"
|
||||||
|
|
||||||
|
var pstStates = ""
|
||||||
|
for (state <- UPFInputs.states.keys) {
|
||||||
|
val stateVal = getStateVal(pd, state)
|
||||||
|
pstStates += s"add_pst_state ${state} -pst pst_table -state { "
|
||||||
|
for (port <- portsList) {
|
||||||
|
if (port == "VDDH") {
|
||||||
|
pstStates += s"HighVoltage "
|
||||||
|
} else if (port == "VDDL") {
|
||||||
|
pstStates += s"LowVoltage "
|
||||||
|
} else { // gated
|
||||||
|
stateVal match {
|
||||||
|
case 0 => pstStates += s"${port}_OFF "
|
||||||
|
case 1 => pstStates += s"HighVoltage "
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pstStates += "}\n"
|
||||||
|
}
|
||||||
|
message += portStates
|
||||||
|
message += createPST
|
||||||
|
message += pstStates
|
||||||
|
message += "\n"
|
||||||
|
return message
|
||||||
|
}
|
||||||
|
|
||||||
|
def getStateVal(pd: PowerDomain, state: String): Int = {
|
||||||
|
val stateVals = UPFInputs.states(state).split(",").map(_.trim.toInt)
|
||||||
|
val index = UPFInputs.domains.indexOf(pd.name)
|
||||||
|
return stateVals(index)
|
||||||
|
}
|
||||||
|
|
||||||
|
// current strategy: for each power domain, create level shifters for outputs going to all other pds
|
||||||
|
// not creating level shifters for inputs since every pd will already shift its outputs
|
||||||
|
// creating level shifters going to every other pd since not sure how to check if there is communication or not between any 2
|
||||||
|
def createLevelShifters(pd: PowerDomain, pdList: List[PowerDomain]): String = {
|
||||||
|
var message = "##### Level Shifters #####\n"
|
||||||
|
for (pd2 <- pdList) {
|
||||||
|
if (pd != pd2) {
|
||||||
|
val voltage1 = pd.mainVoltage
|
||||||
|
val voltage2 = pd2.mainVoltage
|
||||||
|
var subMessage = voltage1 match {
|
||||||
|
case x if x < voltage2 => {
|
||||||
|
s"set_level_shifter LtoH_${pd.name}_to_${pd2.name} " +
|
||||||
|
s"-domain ${pd.name} " +
|
||||||
|
"-applies_to outputs " +
|
||||||
|
"rule low_to_high " +
|
||||||
|
"-location self\n"
|
||||||
|
}
|
||||||
|
case y if y > voltage2 => {
|
||||||
|
s"set_level_shifter HtoL_${pd.name}_to_${pd2.name} " +
|
||||||
|
s"-domain ${pd.name} " +
|
||||||
|
"-applies_to outputs " +
|
||||||
|
"rule high_to_low " +
|
||||||
|
"-location self\n"
|
||||||
|
}
|
||||||
|
case _ => ""
|
||||||
|
}
|
||||||
|
message += subMessage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
message += "\n"
|
||||||
|
return message
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
54
generators/chipyard/src/main/scala/upf/UPFInputs.scala
Normal file
54
generators/chipyard/src/main/scala/upf/UPFInputs.scala
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
// See LICENSE for license details
|
||||||
|
package chipyard.upf
|
||||||
|
|
||||||
|
// outputs are dumped in vlsi/generated-src/upf
|
||||||
|
object UPFInputs {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UPF info
|
||||||
|
* each PowerDomainInput represents a desired power domain
|
||||||
|
* each input will contain all the necessary info to describe a power domain in UPF, including hierarchy
|
||||||
|
*/
|
||||||
|
val upfInfo = List(
|
||||||
|
PowerDomainInput(name="PD_top", isTop=true, moduleList=List("DigitalTop"),
|
||||||
|
parentPD="", childrenPDs=List("PD_RocketTile1", "PD_RocketTile2"),
|
||||||
|
isGated=false, highVoltage=3.9, lowVoltage=3.4),
|
||||||
|
PowerDomainInput(name="PD_RocketTile1", isTop=false, moduleList=List("tile_prci_domain"),
|
||||||
|
parentPD="PD_top", childrenPDs=List(),
|
||||||
|
isGated=false, highVoltage=3.9, lowVoltage=3.1),
|
||||||
|
PowerDomainInput(name="PD_RocketTile2", isTop=false, moduleList=List("tile_prci_domain_1"),
|
||||||
|
parentPD="PD_top", childrenPDs=List(),
|
||||||
|
isGated=false, highVoltage=3.9, lowVoltage=3.2),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PST info
|
||||||
|
* experimental Power State Table input, used to gate power domains based on specified power states
|
||||||
|
* place names of all power domains to be gated in the domains list
|
||||||
|
* states will map different keywords (arbitrary strings) to a binary on or off (1 or 0) to form a power state
|
||||||
|
* order of domains in list corresponds to order of values in each states mapping
|
||||||
|
*/
|
||||||
|
val domains = List("PD_top", "PD_RocketTile1", "PD_RocketTile2")
|
||||||
|
val states = Map(
|
||||||
|
"ON" -> "1, 1, 1",
|
||||||
|
"OFF" -> "0, 0, 0"
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Representation of a power domain used to generate UPF.
|
||||||
|
*
|
||||||
|
* @param name name of the power domain.
|
||||||
|
* @param isTop if the power domain is the top level or not.
|
||||||
|
* @param moduleList refers to all the Verilog modules belonging to this power domain. Can be module name, instance name, or full path name.
|
||||||
|
* @param parentPD the name of the parent power domain to this one.
|
||||||
|
* @param childrenPDs names of all the children power domains to this one.
|
||||||
|
* @param isGated if the power domain is gated or not.
|
||||||
|
* @param highVoltage voltage value of the high voltage rail (currently, gated nets have access to high voltage since they are optimized to save power).
|
||||||
|
* @param lowVoltage voltage value of the low voltage rail (currently, non-gated nets default to the low voltage rail).
|
||||||
|
*/
|
||||||
|
case class PowerDomainInput(name: String, isTop: Boolean, moduleList: List[String],
|
||||||
|
parentPD: String, childrenPDs: List[String],
|
||||||
|
isGated: Boolean, highVoltage: Double, lowVoltage: Double)
|
||||||
@@ -92,7 +92,7 @@ class WithFireSimDesignTweaks extends Config(
|
|||||||
// Optional: reduce the width of the Serial TL interface
|
// Optional: reduce the width of the Serial TL interface
|
||||||
new testchipip.WithSerialTLWidth(4) ++
|
new testchipip.WithSerialTLWidth(4) ++
|
||||||
// Required*: Scale default baud rate with periphery bus frequency
|
// Required*: Scale default baud rate with periphery bus frequency
|
||||||
new chipyard.config.WithUART(BigInt(3686400L)) ++
|
new chipyard.config.WithUARTInitBaudRate(BigInt(3686400L)) ++
|
||||||
// Optional: Adds IO to attach tracerV bridges
|
// Optional: Adds IO to attach tracerV bridges
|
||||||
new chipyard.config.WithTraceIO ++
|
new chipyard.config.WithTraceIO ++
|
||||||
// Optional: Request 16 GiB of target-DRAM by default (can safely request up to 32 GiB on F1)
|
// Optional: Request 16 GiB of target-DRAM by default (can safely request up to 32 GiB on F1)
|
||||||
@@ -241,7 +241,7 @@ class FireSimSmallSystemConfig extends Config(
|
|||||||
new freechips.rocketchip.subsystem.WithExtMemSize(1 << 28) ++
|
new freechips.rocketchip.subsystem.WithExtMemSize(1 << 28) ++
|
||||||
new testchipip.WithDefaultSerialTL ++
|
new testchipip.WithDefaultSerialTL ++
|
||||||
new testchipip.WithBlockDevice ++
|
new testchipip.WithBlockDevice ++
|
||||||
new chipyard.config.WithUART ++
|
new chipyard.config.WithUARTInitBaudRate(BigInt(3686400L)) ++
|
||||||
new freechips.rocketchip.subsystem.WithInclusiveCache(nWays = 2, capacityKB = 64) ++
|
new freechips.rocketchip.subsystem.WithInclusiveCache(nWays = 2, capacityKB = 64) ++
|
||||||
new chipyard.RocketConfig)
|
new chipyard.RocketConfig)
|
||||||
|
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ if run_step "1"; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# use conda-lock to create env
|
# use conda-lock to create env
|
||||||
conda-lock install -p $CYDIR/.conda-env $LOCKFILE
|
conda-lock install --conda $(which conda) -p $CYDIR/.conda-env $LOCKFILE
|
||||||
|
|
||||||
source $CYDIR/.conda-env/etc/profile.d/conda.sh
|
source $CYDIR/.conda-env/etc/profile.d/conda.sh
|
||||||
conda activate $CYDIR/.conda-env
|
conda activate $CYDIR/.conda-env
|
||||||
|
|||||||
@@ -14,5 +14,5 @@ for TOOLCHAIN_TYPE in riscv-tools esp-tools; do
|
|||||||
# note: lock file must end in .conda-lock.yml - see https://github.com/conda-incubator/conda-lock/issues/154
|
# note: lock file must end in .conda-lock.yml - see https://github.com/conda-incubator/conda-lock/issues/154
|
||||||
LOCKFILE=$REQS_DIR/conda-lock-reqs/conda-requirements-$TOOLCHAIN_TYPE-linux-64.conda-lock.yml
|
LOCKFILE=$REQS_DIR/conda-lock-reqs/conda-requirements-$TOOLCHAIN_TYPE-linux-64.conda-lock.yml
|
||||||
|
|
||||||
conda-lock -f "$REQS_DIR/chipyard.yaml" -f "$REQS_DIR/$TOOLCHAIN_TYPE.yaml" -p linux-64 --lockfile $LOCKFILE
|
conda-lock --conda $(which conda) -f "$REQS_DIR/chipyard.yaml" -f "$REQS_DIR/$TOOLCHAIN_TYPE.yaml" -p linux-64 --lockfile $LOCKFILE
|
||||||
done
|
done
|
||||||
|
|||||||
Submodule software/firemarshal updated: f553a22b28...8b8eea35f6
@@ -5,7 +5,7 @@
|
|||||||
#define SPIFLASH_BASE_MEM 0x20000000
|
#define SPIFLASH_BASE_MEM 0x20000000
|
||||||
#define SPIFLASH_BASE_MEM_SIZE 0x10000000
|
#define SPIFLASH_BASE_MEM_SIZE 0x10000000
|
||||||
|
|
||||||
#define SPIFLASH_BASE_CTRL 0x10040000
|
#define SPIFLASH_BASE_CTRL 0x10030000
|
||||||
// Only defining the registers we use; there are more
|
// Only defining the registers we use; there are more
|
||||||
// Software control
|
// Software control
|
||||||
#define SPIFLASH_OFFS_CSMODE 0x18
|
#define SPIFLASH_OFFS_CSMODE 0x18
|
||||||
|
|||||||
Reference in New Issue
Block a user