mirror of
https://github.com/handsomezhuzhu/2025-yatcpu.git
synced 2026-02-20 12:00:14 +00:00
init repo
This commit is contained in:
201
LICENSE
Normal file
201
LICENSE
Normal file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [Tokisakix] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
358
lab1/.gitignore
vendored
Normal file
358
lab1/.gitignore
vendored
Normal file
@@ -0,0 +1,358 @@
|
||||
### Project Specific stuff
|
||||
test_run_dir/*
|
||||
### XilinxISE template
|
||||
# intermediate build files
|
||||
*.bgn
|
||||
*.bit
|
||||
*.bld
|
||||
*.cmd_log
|
||||
*.drc
|
||||
*.ll
|
||||
*.lso
|
||||
*.msd
|
||||
*.msk
|
||||
*.ncd
|
||||
*.ngc
|
||||
*.ngd
|
||||
*.ngr
|
||||
*.pad
|
||||
*.par
|
||||
*.pcf
|
||||
*.prj
|
||||
*.ptwx
|
||||
*.rbb
|
||||
*.rbd
|
||||
*.stx
|
||||
*.syr
|
||||
*.twr
|
||||
*.twx
|
||||
*.unroutes
|
||||
*.ut
|
||||
*.xpi
|
||||
*.xst
|
||||
*_bitgen.xwbt
|
||||
*_envsettings.html
|
||||
*_map.map
|
||||
*_map.mrp
|
||||
*_map.ngm
|
||||
*_map.xrpt
|
||||
*_ngdbuild.xrpt
|
||||
*_pad.csv
|
||||
*_pad.txt
|
||||
*_par.xrpt
|
||||
*_summary.html
|
||||
*_summary.xml
|
||||
*_usage.xml
|
||||
*_xst.xrpt
|
||||
|
||||
# project-wide generated files
|
||||
*.gise
|
||||
par_usage_statistics.html
|
||||
usage_statistics_webtalk.html
|
||||
webtalk.log
|
||||
webtalk_pn.xml
|
||||
|
||||
# generated folders
|
||||
iseconfig/
|
||||
xlnx_auto_0_xdb/
|
||||
xst/
|
||||
_ngo/
|
||||
_xmsgs/
|
||||
### Eclipse template
|
||||
*.pydevproject
|
||||
.metadata
|
||||
.gradle
|
||||
bin/
|
||||
tmp/
|
||||
*.tmp
|
||||
*.bak
|
||||
*.swp
|
||||
*~.nib
|
||||
local.properties
|
||||
.settings/
|
||||
.loadpath
|
||||
|
||||
# Eclipse Core
|
||||
.project
|
||||
|
||||
# External tool builders
|
||||
.externalToolBuilders/
|
||||
|
||||
# Locally stored "Eclipse launch configurations"
|
||||
*.launch
|
||||
|
||||
# CDT-specific
|
||||
.cproject
|
||||
|
||||
# JDT-specific (Eclipse Java Development Tools)
|
||||
.classpath
|
||||
|
||||
# Java annotation processor (APT)
|
||||
.factorypath
|
||||
|
||||
# PDT-specific
|
||||
.buildpath
|
||||
|
||||
# sbteclipse plugin
|
||||
.target
|
||||
|
||||
# TeXlipse plugin
|
||||
.texlipse
|
||||
### C template
|
||||
# Object files
|
||||
*.o
|
||||
*.ko
|
||||
*.obj
|
||||
*.elf
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Libraries
|
||||
*.lib
|
||||
*.a
|
||||
*.la
|
||||
*.lo
|
||||
|
||||
# Shared objects (inc. Windows DLLs)
|
||||
*.dll
|
||||
*.so
|
||||
*.so.*
|
||||
*.dylib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
*.i*86
|
||||
*.x86_64
|
||||
*.hex
|
||||
|
||||
# Debug files
|
||||
*.dSYM/
|
||||
### SBT template
|
||||
# Simple Build Tool
|
||||
# http://www.scala-sbt.org/release/docs/Getting-Started/Directories.html#configuring-version-control
|
||||
|
||||
target/
|
||||
lib_managed/
|
||||
src_managed/
|
||||
project/boot/
|
||||
.history
|
||||
.cache
|
||||
### Emacs template
|
||||
# -*- mode: gitignore; -*-
|
||||
*~
|
||||
\#*\#
|
||||
/.emacs.desktop
|
||||
/.emacs.desktop.lock
|
||||
*.elc
|
||||
auto-save-list
|
||||
tramp
|
||||
.\#*
|
||||
|
||||
# Org-mode
|
||||
.org-id-locations
|
||||
*_archive
|
||||
|
||||
# flymake-mode
|
||||
*_flymake.*
|
||||
|
||||
# eshell files
|
||||
/eshell/history
|
||||
/eshell/lastdir
|
||||
|
||||
# elpa packages
|
||||
/elpa/
|
||||
|
||||
# reftex files
|
||||
*.rel
|
||||
|
||||
# AUCTeX auto folder
|
||||
/auto/
|
||||
|
||||
# cask packages
|
||||
.cask/
|
||||
### Vim template
|
||||
[._]*.s[a-w][a-z]
|
||||
[._]s[a-w][a-z]
|
||||
*.un~
|
||||
Session.vim
|
||||
.netrwhist
|
||||
*~
|
||||
### JetBrains template
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio
|
||||
|
||||
*.iml
|
||||
|
||||
## Directory-based project format:
|
||||
.idea/
|
||||
# if you remove the above rule, at least ignore the following:
|
||||
|
||||
# User-specific stuff:
|
||||
# .idea/workspace.xml
|
||||
# .idea/tasks.xml
|
||||
# .idea/dictionaries
|
||||
|
||||
# Sensitive or high-churn files:
|
||||
# .idea/dataSources.ids
|
||||
# .idea/dataSources.xml
|
||||
# .idea/sqlDataSources.xml
|
||||
# .idea/dynamic.xml
|
||||
# .idea/uiDesigner.xml
|
||||
|
||||
# Gradle:
|
||||
# .idea/gradle.xml
|
||||
# .idea/libraries
|
||||
|
||||
# Mongo Explorer plugin:
|
||||
# .idea/mongoSettings.xml
|
||||
|
||||
## File-based project format:
|
||||
*.ipr
|
||||
*.iws
|
||||
|
||||
## Plugin-specific files:
|
||||
|
||||
# IntelliJ
|
||||
/out/
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
### C++ template
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
*.obj
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
|
||||
# Fortran module files
|
||||
*.mod
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
*.a
|
||||
*.lib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
### OSX template
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Icon must end with two \r
|
||||
Icon
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
### Xcode template
|
||||
# Xcode
|
||||
#
|
||||
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
|
||||
|
||||
## Build generated
|
||||
build/
|
||||
DerivedData
|
||||
|
||||
## Various settings
|
||||
*.pbxuser
|
||||
!default.pbxuser
|
||||
*.mode1v3
|
||||
!default.mode1v3
|
||||
*.mode2v3
|
||||
!default.mode2v3
|
||||
*.perspectivev3
|
||||
!default.perspectivev3
|
||||
xcuserdata
|
||||
|
||||
## Other
|
||||
*.xccheckout
|
||||
*.moved-aside
|
||||
*.xcuserstate
|
||||
### Scala template
|
||||
*.class
|
||||
*.log
|
||||
/.bsp
|
||||
|
||||
# sbt specific
|
||||
.cache
|
||||
.history
|
||||
.lib/
|
||||
dist/*
|
||||
target/
|
||||
lib_managed/
|
||||
src_managed/
|
||||
project/boot/
|
||||
project/plugins/project/
|
||||
|
||||
# Scala-IDE specific
|
||||
.scala_dependencies
|
||||
.worksheet
|
||||
### Java template
|
||||
*.class
|
||||
|
||||
# Mobile Tools for Java (J2ME)
|
||||
.mtj.tmp/
|
||||
|
||||
# Package Files #
|
||||
*.jar
|
||||
*.war
|
||||
*.ear
|
||||
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
hs_err_pid*
|
||||
|
||||
verilog/*.txt
|
||||
verilog/basys3/*
|
||||
verilog/pynq/*
|
||||
verilog/verilator/*
|
||||
!verilog/basys3/test.v
|
||||
!verilog/pynq/design_1_wrapper.v
|
||||
!verilog/pynq/test.v
|
||||
!verilog/pynq/TMDS_PLLVR.v
|
||||
!verilog/verilator/sim_main.cpp
|
||||
*.jou
|
||||
*.log
|
||||
.Xil
|
||||
vivado/basys3/riscv-basys3
|
||||
vivado/pynq/riscv-pynq
|
||||
vivado/pynq/NA
|
||||
.vscode
|
||||
.metals
|
||||
47
lab1/Makefile
Normal file
47
lab1/Makefile
Normal file
@@ -0,0 +1,47 @@
|
||||
# Copyright 2021 Howard Lau
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
test:
|
||||
sbt test
|
||||
|
||||
verilator:
|
||||
sbt "runMain board.verilator.VerilogGenerator"
|
||||
cd verilog/verilator && verilator --trace --exe --cc sim_main.cpp Top.v && make -C obj_dir -f VTop.mk
|
||||
|
||||
verilator-sim: verilator
|
||||
cd verilog/verilator && obj_dir/VTop $(SIM_TIME)
|
||||
|
||||
basys3:
|
||||
sbt "runMain board.basys3.VerilogGenerator"
|
||||
pynq:
|
||||
sbt "runMain board.pynq.VerilogGenerator"
|
||||
|
||||
bitstream-basys3: basys3
|
||||
cd vivado/basys3 && vivado -mode batch -source generate_bitstream.tcl
|
||||
|
||||
program-basys3: bitstream-basys3
|
||||
cd vivado/basys3 && vivado -mode batch -source program_device.tcl
|
||||
|
||||
vivado-sim-basys3: basys3
|
||||
cd vivado/basys3 && vivado -mode batch -source run_simulation.tcl
|
||||
bitstream-pynq: pynq
|
||||
cd vivado/pynq && vivado -mode batch -source generate_bitstream.tcl
|
||||
|
||||
program-pynq: bitstream-pynq
|
||||
cd vivado/pynq && vivado -mode batch -source program_device.tcl
|
||||
|
||||
vivado-sim-pynq: pynq
|
||||
cd vivado/pynq && vivado -mode batch -source run_simulation.tcl
|
||||
|
||||
.PHONY: basys3 verilator test bitstream program verilator-sim vivado-sim
|
||||
24
lab1/build.sbt
Normal file
24
lab1/build.sbt
Normal file
@@ -0,0 +1,24 @@
|
||||
import sbt.Keys.libraryDependencies
|
||||
// See README.md for license details.
|
||||
|
||||
ThisBuild / scalaVersion := "2.13.10"
|
||||
ThisBuild / version := "0.1.0"
|
||||
ThisBuild / organization := "io.github.howardlau1999"
|
||||
|
||||
val chiselVersion = "3.6.0"
|
||||
|
||||
lazy val root = (project in file("."))
|
||||
.settings(
|
||||
name := "yatcpu",
|
||||
libraryDependencies ++= Seq(
|
||||
"edu.berkeley.cs" %% "chisel3" % chiselVersion,
|
||||
"edu.berkeley.cs" %% "chiseltest" % "0.6.0" % "test",
|
||||
),
|
||||
scalacOptions ++= Seq(
|
||||
"-language:reflectiveCalls",
|
||||
"-deprecation",
|
||||
"-feature",
|
||||
"-Xcheckinit",
|
||||
),
|
||||
addCompilerPlugin("edu.berkeley.cs" % "chisel3-plugin" % chiselVersion cross CrossVersion.full),
|
||||
)
|
||||
169
lab1/coremark/yatcpu/core_portme.c
Normal file
169
lab1/coremark/yatcpu/core_portme.c
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC)
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
Original Author: Shay Gal-on
|
||||
*/
|
||||
#include "coremark.h"
|
||||
#include "core_portme.h"
|
||||
|
||||
#if VALIDATION_RUN
|
||||
volatile ee_s32 seed1_volatile = 0x3415;
|
||||
volatile ee_s32 seed2_volatile = 0x3415;
|
||||
volatile ee_s32 seed3_volatile = 0x66;
|
||||
#endif
|
||||
#if PERFORMANCE_RUN
|
||||
volatile ee_s32 seed1_volatile = 0x0;
|
||||
volatile ee_s32 seed2_volatile = 0x0;
|
||||
volatile ee_s32 seed3_volatile = 0x66;
|
||||
#endif
|
||||
#if PROFILE_RUN
|
||||
volatile ee_s32 seed1_volatile = 0x8;
|
||||
volatile ee_s32 seed2_volatile = 0x8;
|
||||
volatile ee_s32 seed3_volatile = 0x8;
|
||||
#endif
|
||||
volatile ee_s32 seed4_volatile = ITERATIONS;
|
||||
volatile ee_s32 seed5_volatile = 0;
|
||||
/* Porting : Timing functions
|
||||
How to capture time and convert to seconds must be ported to whatever is
|
||||
supported by the platform. e.g. Read value from on board RTC, read value from
|
||||
cpu clock cycles performance counter etc. Sample implementation for standard
|
||||
time.h and windows.h definitions included.
|
||||
*/
|
||||
CORETIMETYPE
|
||||
barebones_clock()
|
||||
{
|
||||
ee_u32 cyclel;
|
||||
__asm__ __volatile__ (
|
||||
"rdcycle %0" : "=r"(cyclel) : :
|
||||
);
|
||||
return cyclel;
|
||||
}
|
||||
/* Define : TIMER_RES_DIVIDER
|
||||
Divider to trade off timer resolution and total time that can be
|
||||
measured.
|
||||
|
||||
Use lower values to increase resolution, but make sure that overflow
|
||||
does not occur. If there are issues with the return value overflowing,
|
||||
increase this value.
|
||||
*/
|
||||
#define GETMYTIME(_t) (*_t = barebones_clock())
|
||||
#define MYTIMEDIFF(fin, ini) ((fin) - (ini))
|
||||
#define TIMER_RES_DIVIDER 1
|
||||
#define SAMPLE_TIME_IMPLEMENTATION 1
|
||||
#define EE_TICKS_PER_SEC (CLOCKS_PER_SEC / TIMER_RES_DIVIDER)
|
||||
|
||||
/** Define Host specific (POSIX), or target specific global time variables. */
|
||||
static CORETIMETYPE start_time_val, stop_time_val;
|
||||
|
||||
/* Function : start_time
|
||||
This function will be called right before starting the timed portion of
|
||||
the benchmark.
|
||||
|
||||
Implementation may be capturing a system timer (as implemented in the
|
||||
example code) or zeroing some system parameters - e.g. setting the cpu clocks
|
||||
cycles to 0.
|
||||
*/
|
||||
void
|
||||
start_time(void)
|
||||
{
|
||||
GETMYTIME(&start_time_val);
|
||||
}
|
||||
/* Function : stop_time
|
||||
This function will be called right after ending the timed portion of the
|
||||
benchmark.
|
||||
|
||||
Implementation may be capturing a system timer (as implemented in the
|
||||
example code) or other system parameters - e.g. reading the current value of
|
||||
cpu cycles counter.
|
||||
*/
|
||||
void
|
||||
stop_time(void)
|
||||
{
|
||||
GETMYTIME(&stop_time_val);
|
||||
}
|
||||
/* Function : get_time
|
||||
Return an abstract "ticks" number that signifies time on the system.
|
||||
|
||||
Actual value returned may be cpu cycles, milliseconds or any other
|
||||
value, as long as it can be converted to seconds by <time_in_secs>. This
|
||||
methodology is taken to accommodate any hardware or simulated platform. The
|
||||
sample implementation returns millisecs by default, and the resolution is
|
||||
controlled by <TIMER_RES_DIVIDER>
|
||||
*/
|
||||
CORE_TICKS
|
||||
get_time(void)
|
||||
{
|
||||
CORE_TICKS elapsed
|
||||
= (CORE_TICKS)(MYTIMEDIFF(stop_time_val, start_time_val));
|
||||
return elapsed;
|
||||
}
|
||||
/* Function : time_in_secs
|
||||
Convert the value returned by get_time to seconds.
|
||||
|
||||
The <secs_ret> type is used to accommodate systems with no support for
|
||||
floating point. Default implementation implemented by the EE_TICKS_PER_SEC
|
||||
macro above.
|
||||
*/
|
||||
secs_ret
|
||||
time_in_secs(CORE_TICKS ticks)
|
||||
{
|
||||
secs_ret retval = ((secs_ret)ticks) / (secs_ret)EE_TICKS_PER_SEC;
|
||||
return retval;
|
||||
}
|
||||
|
||||
ee_u32 default_num_contexts = 1;
|
||||
|
||||
/* Function : portable_init
|
||||
Target specific initialization code
|
||||
Test for some common mistakes.
|
||||
*/
|
||||
void
|
||||
portable_init(core_portable *p, int *argc, char *argv[])
|
||||
{
|
||||
if (sizeof(ee_ptr_int) != sizeof(ee_u8 *))
|
||||
{
|
||||
ee_printf(
|
||||
"ERROR! Please define ee_ptr_int to a type that holds a "
|
||||
"pointer!\n");
|
||||
}
|
||||
if (sizeof(ee_u32) != 4)
|
||||
{
|
||||
ee_printf("ERROR! Please define ee_u32 to a 32b unsigned type!\n");
|
||||
}
|
||||
p->portable_id = 1;
|
||||
}
|
||||
/* Function : portable_fini
|
||||
Target specific final code
|
||||
*/
|
||||
void
|
||||
portable_fini(core_portable *p)
|
||||
{
|
||||
p->portable_id = 0;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
__mulsi3 (unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int r = 0;
|
||||
|
||||
while (a)
|
||||
{
|
||||
if (a & 1)
|
||||
r += b;
|
||||
a >>= 1;
|
||||
b <<= 1;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
211
lab1/coremark/yatcpu/core_portme.h
Normal file
211
lab1/coremark/yatcpu/core_portme.h
Normal file
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC)
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
Original Author: Shay Gal-on
|
||||
*/
|
||||
/* Topic : Description
|
||||
This file contains configuration constants required to execute on
|
||||
different platforms
|
||||
*/
|
||||
#ifndef CORE_PORTME_H
|
||||
#define CORE_PORTME_H
|
||||
/************************/
|
||||
/* Data types and settings */
|
||||
/************************/
|
||||
/* Configuration : HAS_FLOAT
|
||||
Define to 1 if the platform supports floating point.
|
||||
*/
|
||||
#ifndef HAS_FLOAT
|
||||
#define HAS_FLOAT 0
|
||||
#endif
|
||||
/* Configuration : HAS_TIME_H
|
||||
Define to 1 if platform has the time.h header file,
|
||||
and implementation of functions thereof.
|
||||
*/
|
||||
#ifndef HAS_TIME_H
|
||||
#define HAS_TIME_H 0
|
||||
#define CLOCKS_PER_SEC 100000000
|
||||
#endif
|
||||
/* Configuration : USE_CLOCK
|
||||
Define to 1 if platform has the time.h header file,
|
||||
and implementation of functions thereof.
|
||||
*/
|
||||
#ifndef USE_CLOCK
|
||||
#define USE_CLOCK 0
|
||||
#endif
|
||||
/* Configuration : HAS_STDIO
|
||||
Define to 1 if the platform has stdio.h.
|
||||
*/
|
||||
#ifndef HAS_STDIO
|
||||
#define HAS_STDIO 0
|
||||
#endif
|
||||
/* Configuration : HAS_PRINTF
|
||||
Define to 1 if the platform has stdio.h and implements the printf
|
||||
function.
|
||||
*/
|
||||
#ifndef HAS_PRINTF
|
||||
#define HAS_PRINTF 0
|
||||
#endif
|
||||
|
||||
/* Definitions : COMPILER_VERSION, COMPILER_FLAGS, MEM_LOCATION
|
||||
Initialize these strings per platform
|
||||
*/
|
||||
#ifndef COMPILER_VERSION
|
||||
#ifdef __GNUC__
|
||||
#define COMPILER_VERSION "GCC"__VERSION__
|
||||
#else
|
||||
#define COMPILER_VERSION "Please put compiler version here (e.g. gcc 4.1)"
|
||||
#endif
|
||||
#endif
|
||||
#ifndef COMPILER_FLAGS
|
||||
#define COMPILER_FLAGS \
|
||||
FLAGS_STR /* "Please put compiler flags here (e.g. -o3)" */
|
||||
#endif
|
||||
#ifndef MEM_LOCATION
|
||||
#define MEM_LOCATION "STACK"
|
||||
#endif
|
||||
|
||||
/* Data Types :
|
||||
To avoid compiler issues, define the data types that need ot be used for
|
||||
8b, 16b and 32b in <core_portme.h>.
|
||||
|
||||
*Imprtant* :
|
||||
ee_ptr_int needs to be the data type used to hold pointers, otherwise
|
||||
coremark may fail!!!
|
||||
*/
|
||||
typedef signed short ee_s16;
|
||||
typedef unsigned short ee_u16;
|
||||
typedef signed int ee_s32;
|
||||
typedef double ee_f32;
|
||||
typedef unsigned char ee_u8;
|
||||
typedef unsigned int ee_u32;
|
||||
typedef ee_u32 ee_ptr_int;
|
||||
typedef ee_u32 ee_size_t;
|
||||
#define NULL ((void *)0)
|
||||
/* align_mem :
|
||||
This macro is used to align an offset to point to a 32b value. It is
|
||||
used in the Matrix algorithm to initialize the input memory blocks.
|
||||
*/
|
||||
#define align_mem(x) (void *)(4 + (((ee_ptr_int)(x)-1) & ~3))
|
||||
|
||||
/* Configuration : CORE_TICKS
|
||||
Define type of return from the timing functions.
|
||||
*/
|
||||
#define CORETIMETYPE ee_u32
|
||||
typedef ee_u32 CORE_TICKS;
|
||||
|
||||
/* Configuration : SEED_METHOD
|
||||
Defines method to get seed values that cannot be computed at compile
|
||||
time.
|
||||
|
||||
Valid values :
|
||||
SEED_ARG - from command line.
|
||||
SEED_FUNC - from a system function.
|
||||
SEED_VOLATILE - from volatile variables.
|
||||
*/
|
||||
#ifndef SEED_METHOD
|
||||
#define SEED_METHOD SEED_VOLATILE
|
||||
#endif
|
||||
|
||||
/* Configuration : MEM_METHOD
|
||||
Defines method to get a block of memry.
|
||||
|
||||
Valid values :
|
||||
MEM_MALLOC - for platforms that implement malloc and have malloc.h.
|
||||
MEM_STATIC - to use a static memory array.
|
||||
MEM_STACK - to allocate the data block on the stack (NYI).
|
||||
*/
|
||||
#ifndef MEM_METHOD
|
||||
#define MEM_METHOD MEM_STATIC
|
||||
#endif
|
||||
|
||||
/* Configuration : MULTITHREAD
|
||||
Define for parallel execution
|
||||
|
||||
Valid values :
|
||||
1 - only one context (default).
|
||||
N>1 - will execute N copies in parallel.
|
||||
|
||||
Note :
|
||||
If this flag is defined to more then 1, an implementation for launching
|
||||
parallel contexts must be defined.
|
||||
|
||||
Two sample implementations are provided. Use <USE_PTHREAD> or <USE_FORK>
|
||||
to enable them.
|
||||
|
||||
It is valid to have a different implementation of <core_start_parallel>
|
||||
and <core_end_parallel> in <core_portme.c>, to fit a particular architecture.
|
||||
*/
|
||||
#ifndef MULTITHREAD
|
||||
#define MULTITHREAD 1
|
||||
#define USE_PTHREAD 0
|
||||
#define USE_FORK 0
|
||||
#define USE_SOCKET 0
|
||||
#endif
|
||||
|
||||
/* Configuration : MAIN_HAS_NOARGC
|
||||
Needed if platform does not support getting arguments to main.
|
||||
|
||||
Valid values :
|
||||
0 - argc/argv to main is supported
|
||||
1 - argc/argv to main is not supported
|
||||
|
||||
Note :
|
||||
This flag only matters if MULTITHREAD has been defined to a value
|
||||
greater then 1.
|
||||
*/
|
||||
#ifndef MAIN_HAS_NOARGC
|
||||
#define MAIN_HAS_NOARGC 1
|
||||
#endif
|
||||
|
||||
/* Configuration : MAIN_HAS_NORETURN
|
||||
Needed if platform does not support returning a value from main.
|
||||
|
||||
Valid values :
|
||||
0 - main returns an int, and return value will be 0.
|
||||
1 - platform does not support returning a value from main
|
||||
*/
|
||||
#ifndef MAIN_HAS_NORETURN
|
||||
#define MAIN_HAS_NORETURN 0
|
||||
#endif
|
||||
|
||||
/* Variable : default_num_contexts
|
||||
Not used for this simple port, must contain the value 1.
|
||||
*/
|
||||
extern ee_u32 default_num_contexts;
|
||||
|
||||
typedef struct CORE_PORTABLE_S
|
||||
{
|
||||
ee_u8 portable_id;
|
||||
} core_portable;
|
||||
|
||||
/* target specific init/fini */
|
||||
void portable_init(core_portable *p, int *argc, char *argv[]);
|
||||
void portable_fini(core_portable *p);
|
||||
|
||||
#if !defined(PROFILE_RUN) && !defined(PERFORMANCE_RUN) \
|
||||
&& !defined(VALIDATION_RUN)
|
||||
#if (TOTAL_DATA_SIZE == 1200)
|
||||
#define PROFILE_RUN 1
|
||||
#elif (TOTAL_DATA_SIZE == 2000)
|
||||
#define PERFORMANCE_RUN 1
|
||||
#else
|
||||
#define VALIDATION_RUN 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
int ee_printf(const char *fmt, ...);
|
||||
|
||||
#endif /* CORE_PORTME_H */
|
||||
92
lab1/coremark/yatcpu/core_portme.mak
Normal file
92
lab1/coremark/yatcpu/core_portme.mak
Normal file
@@ -0,0 +1,92 @@
|
||||
# Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC)
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# Original Author: Shay Gal-on
|
||||
|
||||
#File : core_portme.mak
|
||||
|
||||
# Flag : OUTFLAG
|
||||
# Use this flag to define how to to get an executable (e.g -o)
|
||||
OUTFLAG= -o
|
||||
# Flag : CC
|
||||
# Use this flag to define compiler to use
|
||||
CC = clang
|
||||
# Flag : LD
|
||||
# Use this flag to define compiler to use
|
||||
LD = ld.lld
|
||||
# Flag : AS
|
||||
# Use this flag to define compiler to use
|
||||
AS = clang
|
||||
# Flag : CFLAGS
|
||||
# Use this flag to define compiler options. Note, you can add compiler options from the command line using XCFLAGS="other flags"
|
||||
PORT_CFLAGS = -O0 -g --target=riscv32-unknown-elf -march=rv32i -mabi=ilp32
|
||||
FLAGS_STR = "$(PORT_CFLAGS) $(XCFLAGS) $(XLFLAGS) $(LFLAGS_END)"
|
||||
CFLAGS = $(PORT_CFLAGS) -I$(PORT_DIR) -I. -DFLAGS_STR=\"$(FLAGS_STR)\"
|
||||
#Flag : LFLAGS_END
|
||||
# Define any libraries needed for linking or other flags that should come at the end of the link line (e.g. linker scripts).
|
||||
# Note : On certain platforms, the default clock_gettime implementation is supported but requires linking of librt.
|
||||
SEPARATE_COMPILE=1
|
||||
# Flag : SEPARATE_COMPILE
|
||||
# You must also define below how to create an object file, and how to link.
|
||||
OBJOUT = -o
|
||||
LFLAGS = -T $(PORT_DIR)/link.ld
|
||||
ASFLAGS = -c --target=riscv32-unknown-elf -march=rv32i -mabi=ilp32
|
||||
OFLAG = -o
|
||||
COUT = -c
|
||||
|
||||
LFLAGS_END =
|
||||
# Flag : PORT_SRCS
|
||||
# Port specific source files can be added here
|
||||
# You may also need cvt.c if the fcvt functions are not provided as intrinsics by your compiler!
|
||||
PORT_SRCS = $(PORT_DIR)/core_portme.c $(PORT_DIR)/ee_printf.c $(PORT_DIR)/div.s $(PORT_DIR)/init.s
|
||||
vpath %.c $(PORT_DIR)
|
||||
vpath %.s $(PORT_DIR)
|
||||
|
||||
PORT_OBJS = $(PORT_DIR)/init$(OEXT) $(PORT_DIR)/core_portme$(OEXT) $(PORT_DIR)/ee_printf$(OEXT) $(PORT_DIR)/div$(OEXT)
|
||||
PORT_CLEAN = *$(OEXT) $(OUTFILE).asmbin
|
||||
|
||||
# Flag : LOAD
|
||||
# For a simple port, we assume self hosted compile and run, no load needed.
|
||||
|
||||
# Flag : RUN
|
||||
# For a simple port, we assume self hosted compile and run, simple invocation of the executable
|
||||
|
||||
LOAD = echo "Please set LOAD to the process of loading the executable to the flash"
|
||||
RUN = echo "Please set LOAD to the process of running the executable (e.g. via jtag, or board reset)"
|
||||
|
||||
OEXT = .o
|
||||
EXE = .bin
|
||||
|
||||
$(OPATH)$(PORT_DIR)/%$(OEXT) : %.c
|
||||
$(CC) $(CFLAGS) $(XCFLAGS) $(COUT) $< $(OBJOUT) $@
|
||||
|
||||
$(OPATH)%$(OEXT) : %.c
|
||||
$(CC) $(CFLAGS) $(XCFLAGS) $(COUT) $< $(OBJOUT) $@
|
||||
|
||||
$(OPATH)$(PORT_DIR)/%$(OEXT) : %.s
|
||||
$(AS) $(ASFLAGS) $< $(OBJOUT) $@
|
||||
|
||||
# Target : port_pre% and port_post%
|
||||
# For the purpose of this simple port, no pre or post steps needed.
|
||||
|
||||
.PHONY : port_prebuild port_postbuild port_prerun port_postrun port_preload port_postload
|
||||
port_postbuild: $(OUTFILE)
|
||||
llvm-objcopy -O binary -j .text -j .data $(OUTFILE) $(OUTFILE).asmbin
|
||||
port_pre% port_post% :
|
||||
|
||||
# FLAG : OPATH
|
||||
# Path to the output folder. Default - current folder.
|
||||
OPATH = ./
|
||||
MKDIR = mkdir -p
|
||||
|
||||
127
lab1/coremark/yatcpu/cvt.c
Normal file
127
lab1/coremark/yatcpu/cvt.c
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC)
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#include <math.h>
|
||||
#define CVTBUFSIZE 80
|
||||
static char CVTBUF[CVTBUFSIZE];
|
||||
|
||||
static char *
|
||||
cvt(double arg, int ndigits, int *decpt, int *sign, char *buf, int eflag)
|
||||
{
|
||||
int r2;
|
||||
double fi, fj;
|
||||
char * p, *p1;
|
||||
|
||||
if (ndigits < 0)
|
||||
ndigits = 0;
|
||||
if (ndigits >= CVTBUFSIZE - 1)
|
||||
ndigits = CVTBUFSIZE - 2;
|
||||
r2 = 0;
|
||||
*sign = 0;
|
||||
p = &buf[0];
|
||||
if (arg < 0)
|
||||
{
|
||||
*sign = 1;
|
||||
arg = -arg;
|
||||
}
|
||||
arg = modf(arg, &fi);
|
||||
p1 = &buf[CVTBUFSIZE];
|
||||
|
||||
if (fi != 0)
|
||||
{
|
||||
p1 = &buf[CVTBUFSIZE];
|
||||
while (fi != 0)
|
||||
{
|
||||
fj = modf(fi / 10, &fi);
|
||||
*--p1 = (int)((fj + .03) * 10) + '0';
|
||||
r2++;
|
||||
}
|
||||
while (p1 < &buf[CVTBUFSIZE])
|
||||
*p++ = *p1++;
|
||||
}
|
||||
else if (arg > 0)
|
||||
{
|
||||
while ((fj = arg * 10) < 1)
|
||||
{
|
||||
arg = fj;
|
||||
r2--;
|
||||
}
|
||||
}
|
||||
p1 = &buf[ndigits];
|
||||
if (eflag == 0)
|
||||
p1 += r2;
|
||||
*decpt = r2;
|
||||
if (p1 < &buf[0])
|
||||
{
|
||||
buf[0] = '\0';
|
||||
return buf;
|
||||
}
|
||||
while (p <= p1 && p < &buf[CVTBUFSIZE])
|
||||
{
|
||||
arg *= 10;
|
||||
arg = modf(arg, &fj);
|
||||
*p++ = (int)fj + '0';
|
||||
}
|
||||
if (p1 >= &buf[CVTBUFSIZE])
|
||||
{
|
||||
buf[CVTBUFSIZE - 1] = '\0';
|
||||
return buf;
|
||||
}
|
||||
p = p1;
|
||||
*p1 += 5;
|
||||
while (*p1 > '9')
|
||||
{
|
||||
*p1 = '0';
|
||||
if (p1 > buf)
|
||||
++*--p1;
|
||||
else
|
||||
{
|
||||
*p1 = '1';
|
||||
(*decpt)++;
|
||||
if (eflag == 0)
|
||||
{
|
||||
if (p > buf)
|
||||
*p = '0';
|
||||
p++;
|
||||
}
|
||||
}
|
||||
}
|
||||
*p = '\0';
|
||||
return buf;
|
||||
}
|
||||
|
||||
char *
|
||||
ecvt(double arg, int ndigits, int *decpt, int *sign)
|
||||
{
|
||||
return cvt(arg, ndigits, decpt, sign, CVTBUF, 1);
|
||||
}
|
||||
|
||||
char *
|
||||
ecvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf)
|
||||
{
|
||||
return cvt(arg, ndigits, decpt, sign, buf, 1);
|
||||
}
|
||||
|
||||
char *
|
||||
fcvt(double arg, int ndigits, int *decpt, int *sign)
|
||||
{
|
||||
return cvt(arg, ndigits, decpt, sign, CVTBUF, 0);
|
||||
}
|
||||
|
||||
char *
|
||||
fcvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf)
|
||||
{
|
||||
return cvt(arg, ndigits, decpt, sign, buf, 0);
|
||||
}
|
||||
71
lab1/coremark/yatcpu/div.s
Normal file
71
lab1/coremark/yatcpu/div.s
Normal file
@@ -0,0 +1,71 @@
|
||||
.text
|
||||
.globl __divsi3
|
||||
__divsi3:
|
||||
bltz a0, .L10
|
||||
bltz a1, .L11
|
||||
|
||||
.globl __udivsi3
|
||||
__udivsi3:
|
||||
mv a2, a1
|
||||
mv a1, a0
|
||||
li a0, -1
|
||||
beqz a2, .L5
|
||||
li a3, 1
|
||||
bgeu a2, a1, .L2
|
||||
.L1:
|
||||
blez a2, .L2
|
||||
slli a2, a2, 1
|
||||
slli a3, a3, 1
|
||||
bgtu a1, a2, .L1
|
||||
.L2:
|
||||
li a0, 0
|
||||
.L3:
|
||||
bltu a1, a2, .L4
|
||||
sub a1, a1, a2
|
||||
or a0, a0, a3
|
||||
.L4:
|
||||
srli a3, a3, 1
|
||||
srli a2, a2, 1
|
||||
bnez a3, .L3
|
||||
.L5:
|
||||
ret
|
||||
|
||||
.globl __umodsi3
|
||||
__umodsi3:
|
||||
move t0, ra
|
||||
jal __udivsi3
|
||||
move a0, a1
|
||||
jr t0
|
||||
|
||||
.L10:
|
||||
neg a0, a0
|
||||
bgtz a1, .L12
|
||||
|
||||
neg a1, a1
|
||||
j __udivsi3
|
||||
.L11:
|
||||
neg a1, a1
|
||||
.L12:
|
||||
move t0, ra
|
||||
jal __udivsi3
|
||||
neg a0, a0
|
||||
jr t0
|
||||
|
||||
.globl __modsi3
|
||||
__modsi3:
|
||||
move t0, ra
|
||||
bltz a1, .L31
|
||||
bltz a0, .L32
|
||||
.L30:
|
||||
jal __udivsi3
|
||||
move a0, a1
|
||||
jr t0
|
||||
.L31:
|
||||
neg a1, a1
|
||||
bgez a0, .L30
|
||||
.L32:
|
||||
neg a0, a0
|
||||
jal __udivsi3
|
||||
neg a0, a1
|
||||
jr t0
|
||||
|
||||
687
lab1/coremark/yatcpu/ee_printf.c
Normal file
687
lab1/coremark/yatcpu/ee_printf.c
Normal file
@@ -0,0 +1,687 @@
|
||||
/*
|
||||
Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC)
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#include <coremark.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#define ZEROPAD (1 << 0) /* Pad with zero */
|
||||
#define SIGN (1 << 1) /* Unsigned/signed long */
|
||||
#define PLUS (1 << 2) /* Show plus */
|
||||
#define SPACE (1 << 3) /* Spacer */
|
||||
#define LEFT (1 << 4) /* Left justified */
|
||||
#define HEX_PREP (1 << 5) /* 0x */
|
||||
#define UPPERCASE (1 << 6) /* 'ABCDEF' */
|
||||
|
||||
#define is_digit(c) ((c) >= '0' && (c) <= '9')
|
||||
|
||||
static char * digits = "0123456789abcdefghijklmnopqrstuvwxyz";
|
||||
static char * upper_digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
static ee_size_t strnlen(const char *s, ee_size_t count);
|
||||
|
||||
static ee_size_t
|
||||
strnlen(const char *s, ee_size_t count)
|
||||
{
|
||||
const char *sc;
|
||||
for (sc = s; *sc != '\0' && count--; ++sc)
|
||||
;
|
||||
return sc - s;
|
||||
}
|
||||
|
||||
static int
|
||||
skip_atoi(const char **s)
|
||||
{
|
||||
int i = 0;
|
||||
while (is_digit(**s))
|
||||
i = i * 10 + *((*s)++) - '0';
|
||||
return i;
|
||||
}
|
||||
|
||||
static char *
|
||||
number(char *str, long num, int base, int size, int precision, int type)
|
||||
{
|
||||
char c, sign, tmp[66];
|
||||
char *dig = digits;
|
||||
int i;
|
||||
|
||||
if (type & UPPERCASE)
|
||||
dig = upper_digits;
|
||||
if (type & LEFT)
|
||||
type &= ~ZEROPAD;
|
||||
if (base < 2 || base > 36)
|
||||
return 0;
|
||||
|
||||
c = (type & ZEROPAD) ? '0' : ' ';
|
||||
sign = 0;
|
||||
if (type & SIGN)
|
||||
{
|
||||
if (num < 0)
|
||||
{
|
||||
sign = '-';
|
||||
num = -num;
|
||||
size--;
|
||||
}
|
||||
else if (type & PLUS)
|
||||
{
|
||||
sign = '+';
|
||||
size--;
|
||||
}
|
||||
else if (type & SPACE)
|
||||
{
|
||||
sign = ' ';
|
||||
size--;
|
||||
}
|
||||
}
|
||||
|
||||
if (type & HEX_PREP)
|
||||
{
|
||||
if (base == 16)
|
||||
size -= 2;
|
||||
else if (base == 8)
|
||||
size--;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
|
||||
if (num == 0)
|
||||
tmp[i++] = '0';
|
||||
else
|
||||
{
|
||||
while (num != 0)
|
||||
{
|
||||
tmp[i++] = dig[((unsigned long)num) % (unsigned)base];
|
||||
num = ((unsigned long)num) / (unsigned)base;
|
||||
}
|
||||
}
|
||||
|
||||
if (i > precision)
|
||||
precision = i;
|
||||
size -= precision;
|
||||
if (!(type & (ZEROPAD | LEFT)))
|
||||
while (size-- > 0)
|
||||
*str++ = ' ';
|
||||
if (sign)
|
||||
*str++ = sign;
|
||||
|
||||
if (type & HEX_PREP)
|
||||
{
|
||||
if (base == 8)
|
||||
*str++ = '0';
|
||||
else if (base == 16)
|
||||
{
|
||||
*str++ = '0';
|
||||
*str++ = digits[33];
|
||||
}
|
||||
}
|
||||
|
||||
if (!(type & LEFT))
|
||||
while (size-- > 0)
|
||||
*str++ = c;
|
||||
while (i < precision--)
|
||||
*str++ = '0';
|
||||
while (i-- > 0)
|
||||
*str++ = tmp[i];
|
||||
while (size-- > 0)
|
||||
*str++ = ' ';
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
static char *
|
||||
eaddr(char *str, unsigned char *addr, int size, int precision, int type)
|
||||
{
|
||||
char tmp[24];
|
||||
char *dig = digits;
|
||||
int i, len;
|
||||
|
||||
if (type & UPPERCASE)
|
||||
dig = upper_digits;
|
||||
len = 0;
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
if (i != 0)
|
||||
tmp[len++] = ':';
|
||||
tmp[len++] = dig[addr[i] >> 4];
|
||||
tmp[len++] = dig[addr[i] & 0x0F];
|
||||
}
|
||||
|
||||
if (!(type & LEFT))
|
||||
while (len < size--)
|
||||
*str++ = ' ';
|
||||
for (i = 0; i < len; ++i)
|
||||
*str++ = tmp[i];
|
||||
while (len < size--)
|
||||
*str++ = ' ';
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
static char *
|
||||
iaddr(char *str, unsigned char *addr, int size, int precision, int type)
|
||||
{
|
||||
char tmp[24];
|
||||
int i, n, len;
|
||||
|
||||
len = 0;
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
if (i != 0)
|
||||
tmp[len++] = '.';
|
||||
n = addr[i];
|
||||
|
||||
if (n == 0)
|
||||
tmp[len++] = digits[0];
|
||||
else
|
||||
{
|
||||
if (n >= 100)
|
||||
{
|
||||
tmp[len++] = digits[n / 100];
|
||||
n = n % 100;
|
||||
tmp[len++] = digits[n / 10];
|
||||
n = n % 10;
|
||||
}
|
||||
else if (n >= 10)
|
||||
{
|
||||
tmp[len++] = digits[n / 10];
|
||||
n = n % 10;
|
||||
}
|
||||
|
||||
tmp[len++] = digits[n];
|
||||
}
|
||||
}
|
||||
|
||||
if (!(type & LEFT))
|
||||
while (len < size--)
|
||||
*str++ = ' ';
|
||||
for (i = 0; i < len; ++i)
|
||||
*str++ = tmp[i];
|
||||
while (len < size--)
|
||||
*str++ = ' ';
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
#if HAS_FLOAT
|
||||
|
||||
char * ecvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf);
|
||||
char * fcvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf);
|
||||
static void ee_bufcpy(char *d, char *s, int count);
|
||||
|
||||
void
|
||||
ee_bufcpy(char *pd, char *ps, int count)
|
||||
{
|
||||
char *pe = ps + count;
|
||||
while (ps != pe)
|
||||
*pd++ = *ps++;
|
||||
}
|
||||
|
||||
static void
|
||||
parse_float(double value, char *buffer, char fmt, int precision)
|
||||
{
|
||||
int decpt, sign, exp, pos;
|
||||
char *digits = NULL;
|
||||
char cvtbuf[80];
|
||||
int capexp = 0;
|
||||
int magnitude;
|
||||
|
||||
if (fmt == 'G' || fmt == 'E')
|
||||
{
|
||||
capexp = 1;
|
||||
fmt += 'a' - 'A';
|
||||
}
|
||||
|
||||
if (fmt == 'g')
|
||||
{
|
||||
digits = ecvtbuf(value, precision, &decpt, &sign, cvtbuf);
|
||||
magnitude = decpt - 1;
|
||||
if (magnitude < -4 || magnitude > precision - 1)
|
||||
{
|
||||
fmt = 'e';
|
||||
precision -= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
fmt = 'f';
|
||||
precision -= decpt;
|
||||
}
|
||||
}
|
||||
|
||||
if (fmt == 'e')
|
||||
{
|
||||
digits = ecvtbuf(value, precision + 1, &decpt, &sign, cvtbuf);
|
||||
|
||||
if (sign)
|
||||
*buffer++ = '-';
|
||||
*buffer++ = *digits;
|
||||
if (precision > 0)
|
||||
*buffer++ = '.';
|
||||
ee_bufcpy(buffer, digits + 1, precision);
|
||||
buffer += precision;
|
||||
*buffer++ = capexp ? 'E' : 'e';
|
||||
|
||||
if (decpt == 0)
|
||||
{
|
||||
if (value == 0.0)
|
||||
exp = 0;
|
||||
else
|
||||
exp = -1;
|
||||
}
|
||||
else
|
||||
exp = decpt - 1;
|
||||
|
||||
if (exp < 0)
|
||||
{
|
||||
*buffer++ = '-';
|
||||
exp = -exp;
|
||||
}
|
||||
else
|
||||
*buffer++ = '+';
|
||||
|
||||
buffer[2] = (exp % 10) + '0';
|
||||
exp = exp / 10;
|
||||
buffer[1] = (exp % 10) + '0';
|
||||
exp = exp / 10;
|
||||
buffer[0] = (exp % 10) + '0';
|
||||
buffer += 3;
|
||||
}
|
||||
else if (fmt == 'f')
|
||||
{
|
||||
digits = fcvtbuf(value, precision, &decpt, &sign, cvtbuf);
|
||||
if (sign)
|
||||
*buffer++ = '-';
|
||||
if (*digits)
|
||||
{
|
||||
if (decpt <= 0)
|
||||
{
|
||||
*buffer++ = '0';
|
||||
*buffer++ = '.';
|
||||
for (pos = 0; pos < -decpt; pos++)
|
||||
*buffer++ = '0';
|
||||
while (*digits)
|
||||
*buffer++ = *digits++;
|
||||
}
|
||||
else
|
||||
{
|
||||
pos = 0;
|
||||
while (*digits)
|
||||
{
|
||||
if (pos++ == decpt)
|
||||
*buffer++ = '.';
|
||||
*buffer++ = *digits++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*buffer++ = '0';
|
||||
if (precision > 0)
|
||||
{
|
||||
*buffer++ = '.';
|
||||
for (pos = 0; pos < precision; pos++)
|
||||
*buffer++ = '0';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*buffer = '\0';
|
||||
}
|
||||
|
||||
static void
|
||||
decimal_point(char *buffer)
|
||||
{
|
||||
while (*buffer)
|
||||
{
|
||||
if (*buffer == '.')
|
||||
return;
|
||||
if (*buffer == 'e' || *buffer == 'E')
|
||||
break;
|
||||
buffer++;
|
||||
}
|
||||
|
||||
if (*buffer)
|
||||
{
|
||||
int n = strnlen(buffer, 256);
|
||||
while (n > 0)
|
||||
{
|
||||
buffer[n + 1] = buffer[n];
|
||||
n--;
|
||||
}
|
||||
|
||||
*buffer = '.';
|
||||
}
|
||||
else
|
||||
{
|
||||
*buffer++ = '.';
|
||||
*buffer = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cropzeros(char *buffer)
|
||||
{
|
||||
char *stop;
|
||||
|
||||
while (*buffer && *buffer != '.')
|
||||
buffer++;
|
||||
if (*buffer++)
|
||||
{
|
||||
while (*buffer && *buffer != 'e' && *buffer != 'E')
|
||||
buffer++;
|
||||
stop = buffer--;
|
||||
while (*buffer == '0')
|
||||
buffer--;
|
||||
if (*buffer == '.')
|
||||
buffer--;
|
||||
while (buffer != stop)
|
||||
*++buffer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static char *
|
||||
flt(char *str, double num, int size, int precision, char fmt, int flags)
|
||||
{
|
||||
char tmp[80];
|
||||
char c, sign;
|
||||
int n, i;
|
||||
|
||||
// Left align means no zero padding
|
||||
if (flags & LEFT)
|
||||
flags &= ~ZEROPAD;
|
||||
|
||||
// Determine padding and sign char
|
||||
c = (flags & ZEROPAD) ? '0' : ' ';
|
||||
sign = 0;
|
||||
if (flags & SIGN)
|
||||
{
|
||||
if (num < 0.0)
|
||||
{
|
||||
sign = '-';
|
||||
num = -num;
|
||||
size--;
|
||||
}
|
||||
else if (flags & PLUS)
|
||||
{
|
||||
sign = '+';
|
||||
size--;
|
||||
}
|
||||
else if (flags & SPACE)
|
||||
{
|
||||
sign = ' ';
|
||||
size--;
|
||||
}
|
||||
}
|
||||
|
||||
// Compute the precision value
|
||||
if (precision < 0)
|
||||
precision = 6; // Default precision: 6
|
||||
|
||||
// Convert floating point number to text
|
||||
parse_float(num, tmp, fmt, precision);
|
||||
|
||||
if ((flags & HEX_PREP) && precision == 0)
|
||||
decimal_point(tmp);
|
||||
if (fmt == 'g' && !(flags & HEX_PREP))
|
||||
cropzeros(tmp);
|
||||
|
||||
n = strnlen(tmp, 256);
|
||||
|
||||
// Output number with alignment and padding
|
||||
size -= n;
|
||||
if (!(flags & (ZEROPAD | LEFT)))
|
||||
while (size-- > 0)
|
||||
*str++ = ' ';
|
||||
if (sign)
|
||||
*str++ = sign;
|
||||
if (!(flags & LEFT))
|
||||
while (size-- > 0)
|
||||
*str++ = c;
|
||||
for (i = 0; i < n; i++)
|
||||
*str++ = tmp[i];
|
||||
while (size-- > 0)
|
||||
*str++ = ' ';
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static int
|
||||
ee_vsprintf(char *buf, const char *fmt, va_list args)
|
||||
{
|
||||
int len;
|
||||
unsigned long num;
|
||||
int i, base;
|
||||
char * str;
|
||||
char * s;
|
||||
|
||||
int flags; // Flags to number()
|
||||
|
||||
int field_width; // Width of output field
|
||||
int precision; // Min. # of digits for integers; max number of chars for
|
||||
// from string
|
||||
int qualifier; // 'h', 'l', or 'L' for integer fields
|
||||
|
||||
for (str = buf; *fmt; fmt++)
|
||||
{
|
||||
if (*fmt != '%')
|
||||
{
|
||||
*str++ = *fmt;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Process flags
|
||||
flags = 0;
|
||||
repeat:
|
||||
fmt++; // This also skips first '%'
|
||||
switch (*fmt)
|
||||
{
|
||||
case '-':
|
||||
flags |= LEFT;
|
||||
goto repeat;
|
||||
case '+':
|
||||
flags |= PLUS;
|
||||
goto repeat;
|
||||
case ' ':
|
||||
flags |= SPACE;
|
||||
goto repeat;
|
||||
case '#':
|
||||
flags |= HEX_PREP;
|
||||
goto repeat;
|
||||
case '0':
|
||||
flags |= ZEROPAD;
|
||||
goto repeat;
|
||||
}
|
||||
|
||||
// Get field width
|
||||
field_width = -1;
|
||||
if (is_digit(*fmt))
|
||||
field_width = skip_atoi(&fmt);
|
||||
else if (*fmt == '*')
|
||||
{
|
||||
fmt++;
|
||||
field_width = va_arg(args, int);
|
||||
if (field_width < 0)
|
||||
{
|
||||
field_width = -field_width;
|
||||
flags |= LEFT;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the precision
|
||||
precision = -1;
|
||||
if (*fmt == '.')
|
||||
{
|
||||
++fmt;
|
||||
if (is_digit(*fmt))
|
||||
precision = skip_atoi(&fmt);
|
||||
else if (*fmt == '*')
|
||||
{
|
||||
++fmt;
|
||||
precision = va_arg(args, int);
|
||||
}
|
||||
if (precision < 0)
|
||||
precision = 0;
|
||||
}
|
||||
|
||||
// Get the conversion qualifier
|
||||
qualifier = -1;
|
||||
if (*fmt == 'l' || *fmt == 'L')
|
||||
{
|
||||
qualifier = *fmt;
|
||||
fmt++;
|
||||
}
|
||||
|
||||
// Default base
|
||||
base = 10;
|
||||
|
||||
switch (*fmt)
|
||||
{
|
||||
case 'c':
|
||||
if (!(flags & LEFT))
|
||||
while (--field_width > 0)
|
||||
*str++ = ' ';
|
||||
*str++ = (unsigned char)va_arg(args, int);
|
||||
while (--field_width > 0)
|
||||
*str++ = ' ';
|
||||
continue;
|
||||
|
||||
case 's':
|
||||
s = va_arg(args, char *);
|
||||
if (!s)
|
||||
s = "<NULL>";
|
||||
len = strnlen(s, precision);
|
||||
if (!(flags & LEFT))
|
||||
while (len < field_width--)
|
||||
*str++ = ' ';
|
||||
for (i = 0; i < len; ++i)
|
||||
*str++ = *s++;
|
||||
while (len < field_width--)
|
||||
*str++ = ' ';
|
||||
continue;
|
||||
|
||||
case 'p':
|
||||
if (field_width == -1)
|
||||
{
|
||||
field_width = 2 * sizeof(void *);
|
||||
flags |= ZEROPAD;
|
||||
}
|
||||
str = number(str,
|
||||
(unsigned long)va_arg(args, void *),
|
||||
16,
|
||||
field_width,
|
||||
precision,
|
||||
flags);
|
||||
continue;
|
||||
|
||||
case 'A':
|
||||
flags |= UPPERCASE;
|
||||
|
||||
case 'a':
|
||||
if (qualifier == 'l')
|
||||
str = eaddr(str,
|
||||
va_arg(args, unsigned char *),
|
||||
field_width,
|
||||
precision,
|
||||
flags);
|
||||
else
|
||||
str = iaddr(str,
|
||||
va_arg(args, unsigned char *),
|
||||
field_width,
|
||||
precision,
|
||||
flags);
|
||||
continue;
|
||||
|
||||
// Integer number formats - set up the flags and "break"
|
||||
case 'o':
|
||||
base = 8;
|
||||
break;
|
||||
|
||||
case 'X':
|
||||
flags |= UPPERCASE;
|
||||
|
||||
case 'x':
|
||||
base = 16;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
case 'i':
|
||||
flags |= SIGN;
|
||||
|
||||
case 'u':
|
||||
break;
|
||||
|
||||
#if HAS_FLOAT
|
||||
|
||||
case 'f':
|
||||
str = flt(str,
|
||||
va_arg(args, double),
|
||||
field_width,
|
||||
precision,
|
||||
*fmt,
|
||||
flags | SIGN);
|
||||
continue;
|
||||
|
||||
#endif
|
||||
|
||||
default:
|
||||
if (*fmt != '%')
|
||||
*str++ = '%';
|
||||
if (*fmt)
|
||||
*str++ = *fmt;
|
||||
else
|
||||
--fmt;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (qualifier == 'l')
|
||||
num = va_arg(args, unsigned long);
|
||||
else if (flags & SIGN)
|
||||
num = va_arg(args, int);
|
||||
else
|
||||
num = va_arg(args, unsigned int);
|
||||
|
||||
str = number(str, num, base, field_width, precision, flags);
|
||||
}
|
||||
|
||||
*str = '\0';
|
||||
return str - buf;
|
||||
}
|
||||
|
||||
void
|
||||
uart_send_char(char c)
|
||||
{
|
||||
*((volatile unsigned int *) (0x40000010)) = c;
|
||||
}
|
||||
|
||||
int
|
||||
ee_printf(const char *fmt, ...)
|
||||
{
|
||||
char buf[1024], *p;
|
||||
va_list args;
|
||||
int n = 0;
|
||||
|
||||
va_start(args, fmt);
|
||||
ee_vsprintf(buf, fmt, args);
|
||||
va_end(args);
|
||||
p = buf;
|
||||
while (*p)
|
||||
{
|
||||
uart_send_char(*p);
|
||||
n++;
|
||||
p++;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
16
lab1/coremark/yatcpu/init.s
Normal file
16
lab1/coremark/yatcpu/init.s
Normal file
@@ -0,0 +1,16 @@
|
||||
.section .text.init
|
||||
.globl _start
|
||||
_start:
|
||||
li sp, 4092
|
||||
call main
|
||||
li x1, 0xBABECAFE
|
||||
write_tohost:
|
||||
sw x1, tohost, x0
|
||||
loop:
|
||||
j loop
|
||||
|
||||
.pushsection .tohost,"aw",@progbits
|
||||
.align 4
|
||||
.global tohost
|
||||
tohost: .word 0
|
||||
.popsection
|
||||
12
lab1/coremark/yatcpu/link.ld
Normal file
12
lab1/coremark/yatcpu/link.ld
Normal file
@@ -0,0 +1,12 @@
|
||||
OUTPUT_ARCH( "riscv" )
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x00001000;
|
||||
.text : { *(.text.init) *(.text.startup) *(.text) }
|
||||
.data ALIGN(0x1000) : { *(.data*) *(.rodata*) *(.sdata*) }
|
||||
.tohost ALIGN(0x1000) : { *(.tohost) }
|
||||
.bss : { *(.bss) }
|
||||
_end = .;
|
||||
}
|
||||
43
lab1/csrc/CMakeLists.txt
Normal file
43
lab1/csrc/CMakeLists.txt
Normal file
@@ -0,0 +1,43 @@
|
||||
# Make CMake happy
|
||||
cmake_minimum_required(VERSION 3.18)
|
||||
project(yatcpu-programs C CXX ASM)
|
||||
|
||||
# Setting variables
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 --target=riscv32-unknown-elf -march=rv32i -mabi=ilp32")
|
||||
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -O0 --target=riscv32-unknown-elf -march=rv32i -mabi=ilp32")
|
||||
set(C_PROGRAMS tetris hello fibonacci quicksort)
|
||||
set(ASM_PROGRAMS mmio sb)
|
||||
set(LINKER_SCRIPT ${CMAKE_SOURCE_DIR}/link.lds)
|
||||
set(LINKER_FLAGS -T ${LINKER_SCRIPT})
|
||||
set(OBJCOPY_ARGS -O binary -j .text -j .data)
|
||||
if(NOT DEST_DIR)
|
||||
set(DEST_DIR "../src/main/resources")
|
||||
endif()
|
||||
|
||||
# Let CMake know that there exists header files
|
||||
include_directories("${CMAKE_SOURCE_DIR}")
|
||||
|
||||
add_library(prelude init.S)
|
||||
set_target_properties(prelude PROPERTIES LINK_DEPENDS ${LINKER_SCRIPT})
|
||||
|
||||
# Let's build our executables
|
||||
foreach(program IN LISTS C_PROGRAMS)
|
||||
add_executable(${program} ${program}.c)
|
||||
set_target_properties(${program} PROPERTIES LINK_DEPENDS ${LINKER_SCRIPT})
|
||||
target_link_libraries(${program} prelude ${LINKER_FLAGS})
|
||||
endforeach()
|
||||
|
||||
foreach(program IN LISTS ASM_PROGRAMS)
|
||||
add_executable(${program} ${program}.S)
|
||||
set_target_properties(${program} PROPERTIES LINK_DEPENDS ${LINKER_SCRIPT})
|
||||
endforeach()
|
||||
|
||||
# Copy the .text section to .asmbin files
|
||||
foreach(program IN LISTS C_PROGRAMS ASM_PROGRAMS)
|
||||
add_custom_command(
|
||||
TARGET ${program}
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_OBJCOPY} ARGS ${OBJCOPY_ARGS} $<TARGET_FILE:${program}> ${CMAKE_SOURCE_DIR}/${DEST_DIR}/${program}.asmbin
|
||||
)
|
||||
endforeach()
|
||||
|
||||
3
lab1/csrc/build.bat
Normal file
3
lab1/csrc/build.bat
Normal file
@@ -0,0 +1,3 @@
|
||||
rmdir /Q /S build
|
||||
cmake -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake -G"NMake Makefiles" -B build .
|
||||
cmake --build build
|
||||
3
lab1/csrc/build.sh
Normal file
3
lab1/csrc/build.sh
Normal file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
rm -rf build
|
||||
cmake -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake -B build . && cmake --build build --parallel `nproc`
|
||||
22
lab1/csrc/fibonacci.c
Normal file
22
lab1/csrc/fibonacci.c
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright 2021 Howard Lau
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
int fib(int a) {
|
||||
if (a == 1 || a == 2) return 1;
|
||||
return fib(a - 1) + fib(a - 2);
|
||||
}
|
||||
|
||||
int main() {
|
||||
*(int *)(4) = fib(10);
|
||||
}
|
||||
29
lab1/csrc/hdmi_test.c
Normal file
29
lab1/csrc/hdmi_test.c
Normal file
@@ -0,0 +1,29 @@
|
||||
// Copyright 2022 hrpccs
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#include "mmio.h"
|
||||
|
||||
|
||||
|
||||
int main(){
|
||||
int *vram = ((int *) VRAM_BASE);
|
||||
for (int i = 0; i < 600; ++i) vram[i] = 0x20202020;
|
||||
|
||||
for(int i = 0;i < 12;i++){
|
||||
VRAM[i] = "hello world!"[i];
|
||||
}
|
||||
|
||||
while(1);
|
||||
}
|
||||
175
lab1/csrc/hello.c
Normal file
175
lab1/csrc/hello.c
Normal file
@@ -0,0 +1,175 @@
|
||||
// Copyright 2021 Howard Lau
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "mmio.h"
|
||||
|
||||
#define MUL80(x) (((x) << 6) + ((x) << 4))
|
||||
|
||||
struct screen {
|
||||
unsigned char row, col;
|
||||
} scr;
|
||||
|
||||
void copy_line(int prev, int cur) {
|
||||
int *prev_vram_start = ((int *) (MUL80(prev) + VRAM_BASE));
|
||||
int *cur_vram_start = ((int *) (MUL80(cur) + VRAM_BASE));
|
||||
for (int i = 0; i < 20; ++i) {
|
||||
prev_vram_start[i] = cur_vram_start[i];
|
||||
}
|
||||
}
|
||||
|
||||
void write_char(int row, int col, unsigned char ch) {
|
||||
VRAM[MUL80(row) + col] = ch;
|
||||
}
|
||||
|
||||
void move_to(int row, int col) {
|
||||
scr.row = row;
|
||||
scr.col = col;
|
||||
}
|
||||
|
||||
void new_line() {
|
||||
scr.col = 0;
|
||||
if (scr.row == 29) {
|
||||
for (int i = 0; i < 29; ++i) {
|
||||
copy_line(i, i + 1);
|
||||
}
|
||||
int *vram = (int *) (MUL80(29) + VRAM_BASE);
|
||||
for (int i = 0; i < 20; ++i) {
|
||||
vram[i] = 0x20202020;
|
||||
}
|
||||
} else {
|
||||
++scr.row;
|
||||
}
|
||||
}
|
||||
|
||||
void putch(unsigned char ch) {
|
||||
if (ch == '\n') {
|
||||
new_line();
|
||||
} else if (ch == '\r') {
|
||||
scr.col = 0;
|
||||
} else {
|
||||
if (scr.col == 79) {
|
||||
new_line();
|
||||
}
|
||||
write_char(scr.row, scr.col, ch);
|
||||
++scr.col;
|
||||
}
|
||||
}
|
||||
|
||||
void clear_screen() {
|
||||
scr.row = 0;
|
||||
scr.col = 0;
|
||||
int *vram = ((int *) VRAM_BASE);
|
||||
for (int i = 0; i < 600; ++i) vram[i] = 0x20202020;
|
||||
}
|
||||
|
||||
void print_hex(unsigned int counter) {
|
||||
putch('0'); putch('x');
|
||||
for (int i = 7; i >= 0; --i) {
|
||||
unsigned int num = (counter >> (i << 2)) & 0xF;
|
||||
if (num < 10) {
|
||||
putch('0' + num);
|
||||
} else {
|
||||
putch('A' + num - 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void putstr(const char *s) {
|
||||
while (*s) {
|
||||
putch(*(s++));
|
||||
}
|
||||
}
|
||||
|
||||
int hc = 1;
|
||||
int fast = 0;
|
||||
|
||||
void print_timer() {
|
||||
putstr("Hardware timer count limit = ");
|
||||
print_hex(*TIMER_LIMIT);
|
||||
putstr(", enabled = ");
|
||||
print_hex(*TIMER_ENABLED);
|
||||
putch('\n');
|
||||
}
|
||||
|
||||
void print_uart() {
|
||||
putstr("UART Baud rate = ");
|
||||
print_hex(*UART_BAUDRATE);
|
||||
putch('\n');
|
||||
}
|
||||
|
||||
void handle_timer() {
|
||||
putstr("Timer trigger times = ");
|
||||
print_hex(hc++);
|
||||
putch('\n');
|
||||
int mode = ((hc & 0x10) >> 4);
|
||||
if (hc == 0x40) {
|
||||
putstr("Disable timer!\n");
|
||||
*TIMER_ENABLED = 0;
|
||||
print_timer();
|
||||
return;
|
||||
}
|
||||
if (fast ^ mode) {
|
||||
putstr("Switch timer frequency\n");
|
||||
if (fast == 0) {
|
||||
*TIMER_LIMIT = 25000000;
|
||||
} else {
|
||||
|
||||
*TIMER_LIMIT = 100000000;
|
||||
}
|
||||
fast = mode;
|
||||
print_timer();
|
||||
}
|
||||
}
|
||||
|
||||
void handle_uart() {
|
||||
unsigned int ch = *UART_RECV;
|
||||
*UART_SEND = ch;
|
||||
putstr("UART Recv hex = "); print_hex(ch); putstr(", ch = "); putch(ch); putch('\n');
|
||||
}
|
||||
|
||||
void trap_handler(void *epc, unsigned int cause) {
|
||||
putstr("Interrupt! EPC = ");
|
||||
print_hex((unsigned int) epc);
|
||||
putstr(", CAUSE = ");
|
||||
print_hex(cause);
|
||||
putch('\n');
|
||||
switch (cause) {
|
||||
case 0x8000000B:
|
||||
handle_uart();
|
||||
break;
|
||||
default:
|
||||
handle_timer();
|
||||
break;
|
||||
}
|
||||
}
|
||||
extern void enable_interrupt();
|
||||
extern unsigned int get_epc();
|
||||
int main() {
|
||||
clear_screen();
|
||||
hc = 0;
|
||||
*TIMER_ENABLED = 1;
|
||||
putstr("YatCPU Demo Program ");
|
||||
putch(137);
|
||||
putstr("2021 Howard Lau\n");
|
||||
putstr("Hello, world!\n");
|
||||
putstr("Last EPC = ");
|
||||
print_hex(get_epc());
|
||||
putch('\n');
|
||||
print_timer();
|
||||
print_uart();
|
||||
*((int *) 0x4) = 0xDEADBEEF;
|
||||
unsigned int i = 0;
|
||||
enable_interrupt();
|
||||
for (;;) ;
|
||||
}
|
||||
107
lab1/csrc/init.S
Normal file
107
lab1/csrc/init.S
Normal file
@@ -0,0 +1,107 @@
|
||||
# Copyright 2021 Howard Lau
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
.section .text.init
|
||||
.globl _start
|
||||
_start:
|
||||
li sp, 4096 # Initialize stack pointer
|
||||
call main # Jump to main function
|
||||
loop:
|
||||
j loop # Loop forever
|
||||
.globl enable_interrupt
|
||||
enable_interrupt:
|
||||
la t0, __trap_entry
|
||||
csrrw t1, mtvec, t0 # setup trap vector base
|
||||
li t0, 0x1888
|
||||
csrrw t1, mstatus, t0 # enable interrupt
|
||||
ret
|
||||
.globl get_epc
|
||||
get_epc:
|
||||
csrr a0, mepc
|
||||
ret
|
||||
.weak trap_handler
|
||||
tran_handler:
|
||||
ret
|
||||
__trap_entry:
|
||||
csrw mscratch, sp
|
||||
addi sp, sp, -128
|
||||
sw ra, 4(sp)
|
||||
|
||||
sw gp, 12(sp)
|
||||
sw tp, 16(sp)
|
||||
sw t0, 20(sp)
|
||||
sw t1, 24(sp)
|
||||
sw t2, 28(sp)
|
||||
sw tp, 32(sp)
|
||||
sw s1, 36(sp)
|
||||
sw a0, 40(sp)
|
||||
sw a1, 44(sp)
|
||||
sw a2, 48(sp)
|
||||
sw a3, 52(sp)
|
||||
sw a4, 56(sp)
|
||||
sw a5, 60(sp)
|
||||
sw a6, 64(sp)
|
||||
sw a7, 68(sp)
|
||||
sw s2, 72(sp)
|
||||
sw s3, 76(sp)
|
||||
sw s4, 80(sp)
|
||||
sw s5, 84(sp)
|
||||
sw s6, 88(sp)
|
||||
sw s7, 92(sp)
|
||||
sw s8, 96(sp)
|
||||
sw s9, 100(sp)
|
||||
sw s10, 104(sp)
|
||||
sw s11, 108(sp)
|
||||
sw t3, 112(sp)
|
||||
sw t4, 116(sp)
|
||||
sw t5, 120(sp)
|
||||
sw t6, 124(sp)
|
||||
|
||||
csrr a0, mepc
|
||||
csrr a1, mcause
|
||||
call trap_handler
|
||||
|
||||
lw ra, 4(sp)
|
||||
|
||||
lw gp, 12(sp)
|
||||
lw tp, 16(sp)
|
||||
lw t0, 20(sp)
|
||||
lw t1, 24(sp)
|
||||
lw t2, 28(sp)
|
||||
lw tp, 32(sp)
|
||||
lw s1, 36(sp)
|
||||
lw a0, 40(sp)
|
||||
lw a1, 44(sp)
|
||||
lw a2, 48(sp)
|
||||
lw a3, 52(sp)
|
||||
lw a4, 56(sp)
|
||||
lw a5, 60(sp)
|
||||
lw a6, 64(sp)
|
||||
lw a7, 68(sp)
|
||||
lw s2, 72(sp)
|
||||
lw s3, 76(sp)
|
||||
lw s4, 80(sp)
|
||||
lw s5, 84(sp)
|
||||
lw s6, 88(sp)
|
||||
lw s7, 92(sp)
|
||||
lw s8, 96(sp)
|
||||
lw s9, 100(sp)
|
||||
lw s10, 104(sp)
|
||||
lw s11, 108(sp)
|
||||
lw t3, 112(sp)
|
||||
lw t4, 116(sp)
|
||||
lw t5, 120(sp)
|
||||
lw t6, 124(sp)
|
||||
csrr sp, mscratch
|
||||
mret
|
||||
11
lab1/csrc/link.lds
Normal file
11
lab1/csrc/link.lds
Normal file
@@ -0,0 +1,11 @@
|
||||
OUTPUT_ARCH( "riscv" )
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x00001000;
|
||||
.text : { *(.text.init) *(.text.startup) *(.text) }
|
||||
.data ALIGN(0x1000) : { *(.data*) *(.rodata*) *(.sdata*) }
|
||||
.bss : { *(.bss) }
|
||||
_end = .;
|
||||
}
|
||||
24
lab1/csrc/mmio.S
Normal file
24
lab1/csrc/mmio.S
Normal file
@@ -0,0 +1,24 @@
|
||||
# Copyright 2021 Howard Lau
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
.globl _start
|
||||
_start:
|
||||
li a0, 0x80000000
|
||||
lw t0, 4(a0)
|
||||
li a1, 0xBEEF
|
||||
sw a1, 4(a0)
|
||||
nop
|
||||
lw t1, 4(a0)
|
||||
loop:
|
||||
j loop
|
||||
23
lab1/csrc/mmio.h
Normal file
23
lab1/csrc/mmio.h
Normal file
@@ -0,0 +1,23 @@
|
||||
// Copyright 2021 Howard Lau
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#define VRAM_BASE 0x20000000
|
||||
#define VRAM ((volatile unsigned char *) VRAM_BASE)
|
||||
#define TIMER_BASE 0x80000000
|
||||
#define TIMER_LIMIT ((volatile unsigned int *) (TIMER_BASE + 4))
|
||||
#define TIMER_ENABLED ((volatile unsigned int *) (TIMER_BASE + 8))
|
||||
#define UART_BASE 0x40000000
|
||||
#define UART_BAUDRATE ((volatile unsigned int *) (UART_BASE + 4))
|
||||
#define UART_RECV ((volatile unsigned int *) (UART_BASE + 12))
|
||||
#define UART_SEND ((volatile unsigned int *) (UART_BASE + 16))
|
||||
50
lab1/csrc/quicksort.c
Normal file
50
lab1/csrc/quicksort.c
Normal file
@@ -0,0 +1,50 @@
|
||||
// Copyright 2021 Howard Lau
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
void quicksort(int *arr, int l, int r) {
|
||||
if (l >= r) return;
|
||||
int pivot = arr[l];
|
||||
int i = l, j = r;
|
||||
while (i < j) {
|
||||
while(arr[j] >= pivot && i < j) --j;
|
||||
arr[i] = arr[j];
|
||||
while(arr[i] < pivot && i < j) ++i;
|
||||
arr[j] = arr[i];
|
||||
}
|
||||
arr[i] = pivot;
|
||||
quicksort(arr, l, i - 1);
|
||||
quicksort(arr, i + 1, r);
|
||||
}
|
||||
|
||||
int main() {
|
||||
int nums[10];
|
||||
|
||||
nums[0] = 6;
|
||||
nums[1] = 2;
|
||||
nums[2] = 4;
|
||||
nums[3] = 5;
|
||||
nums[4] = 3;
|
||||
nums[5] = 1;
|
||||
nums[6] = 0;
|
||||
nums[7] = 9;
|
||||
nums[8] = 7;
|
||||
nums[9] = 8;
|
||||
|
||||
|
||||
quicksort(nums, 0, 9);
|
||||
|
||||
for (int i = 1; i <= 10; ++i) {
|
||||
*(int *)(i * 4) = nums[i - 1];
|
||||
}
|
||||
}
|
||||
25
lab1/csrc/sb.S
Normal file
25
lab1/csrc/sb.S
Normal file
@@ -0,0 +1,25 @@
|
||||
# Copyright 2021 Howard Lau
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
.globl _start
|
||||
_start:
|
||||
li a0, 0x4
|
||||
li t0, 0xDEADBEEF
|
||||
sb t0, 0(a0)
|
||||
lw t1, 0(a0)
|
||||
li s2, 0x15
|
||||
sb s2, 1(a0)
|
||||
lw ra, 0(a0)
|
||||
loop:
|
||||
j loop
|
||||
498
lab1/csrc/tetris.c
Normal file
498
lab1/csrc/tetris.c
Normal file
@@ -0,0 +1,498 @@
|
||||
// Copyright 2021 Howard Lau
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#include "mmio.h"
|
||||
|
||||
#define FALL_TIMER_LIMIT 50000000
|
||||
#define ROWS 22
|
||||
#define COLS 10
|
||||
#define OFFSET_X 28
|
||||
#define OFFSET_Y 3
|
||||
#define SCREEN_COLS 80
|
||||
#define SCREEN_ROWS 30
|
||||
|
||||
struct block {
|
||||
unsigned int shape[3];
|
||||
unsigned int xywh;
|
||||
};
|
||||
|
||||
struct block current;
|
||||
|
||||
unsigned int score;
|
||||
|
||||
unsigned char *board;
|
||||
|
||||
#ifdef DEBUG
|
||||
unsigned char screen[SCREEN_COLS * SCREEN_ROWS];
|
||||
#endif
|
||||
|
||||
int wk_mul(int a, int b) {
|
||||
int r = 0;
|
||||
for (; b; a <<= 1, b >>= 1)
|
||||
if (b & 1)
|
||||
r += a;
|
||||
return r;
|
||||
}
|
||||
|
||||
unsigned int make_xywh(unsigned int x, unsigned int y, unsigned int w, unsigned int h) {
|
||||
return (x << 12) | (y << 4) | (w << 2) | h;
|
||||
}
|
||||
|
||||
void init_block(struct block *block, int type, int x, int y) {
|
||||
int w = 0; int h = 0;
|
||||
block->shape[0] = block->shape[1] = block->shape[2] = 0;
|
||||
switch(type) {
|
||||
case 0: // I
|
||||
block->shape[0] = 0xF;
|
||||
w = 3; h = 0;
|
||||
break;
|
||||
case 1: // O
|
||||
block->shape[0] = 0x3;
|
||||
block->shape[1] = 0x3;
|
||||
w = 1; h = 1;
|
||||
break;
|
||||
case 2: // J
|
||||
block->shape[0] = 0x4;
|
||||
block->shape[1] = 0x7;
|
||||
w = 2; h = 1;
|
||||
break;
|
||||
case 3: // T
|
||||
block->shape[0] = 0x2;
|
||||
block->shape[1] = 0x7;
|
||||
w = 2; h = 1;
|
||||
break;
|
||||
case 4: // L
|
||||
block->shape[0] = 0x1;
|
||||
block->shape[1] = 0x7;
|
||||
w = 2; h = 1;
|
||||
break;
|
||||
case 5: // Z
|
||||
block->shape[0] = 0x6;
|
||||
block->shape[1] = 0x3;
|
||||
w = 2; h = 1;
|
||||
break;
|
||||
case 6: // S
|
||||
block->shape[0] = 0x3;
|
||||
block->shape[1] = 0x6;
|
||||
w = 2; h = 1;
|
||||
break;
|
||||
}
|
||||
block->xywh = make_xywh(x, y, w, h);
|
||||
}
|
||||
|
||||
unsigned int get_shape(struct block *block, unsigned int r, unsigned int c) {
|
||||
return (block->shape[r] & (1 << c)) >> c;
|
||||
}
|
||||
|
||||
unsigned int check_bounds(struct block *block) {
|
||||
unsigned int xywh = block->xywh;
|
||||
unsigned int h = xywh & 0x3;
|
||||
unsigned int w = (xywh & 0xC) >> 2;
|
||||
unsigned int y = (xywh & 0xFF0) >> 4;
|
||||
unsigned int x = (xywh & 0xF000) >> 12;
|
||||
if (x < 0 || x + w >= COLS) return 0;
|
||||
if (y < 0 || y + h >= ROWS) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void copy_block(struct block *dst, struct block *src) {
|
||||
dst->xywh = src->xywh;
|
||||
dst->shape[0] = src->shape[0];
|
||||
dst->shape[1] = src->shape[1];
|
||||
dst->shape[2] = src->shape[2];
|
||||
}
|
||||
|
||||
unsigned int check_collision(struct block *block) {
|
||||
unsigned int xywh = block->xywh;
|
||||
unsigned int h = xywh & 0x3;
|
||||
unsigned int w = (xywh & 0xC) >> 2;
|
||||
unsigned int y = (xywh & 0xFF0) >> 4;
|
||||
unsigned int x = (xywh & 0xF000) >> 12;
|
||||
for (int r = 0; r <= h; ++r) {
|
||||
for (int c = 0; c <= w; ++c) {
|
||||
if (get_shape(block, r, c) &&
|
||||
board[wk_mul(y + r, COLS) + x + c])
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void putch_at(int x, int y, unsigned char ch) {
|
||||
#ifdef DEBUG
|
||||
screen[wk_mul(OFFSET_Y + y, SCREEN_COLS) + x + OFFSET_X] = ch;
|
||||
#else
|
||||
VRAM[wk_mul(OFFSET_Y + y, SCREEN_COLS) + x + OFFSET_X] = ch;
|
||||
#endif
|
||||
}
|
||||
|
||||
void block_move(struct block *block, int dir) {
|
||||
unsigned int xywh = block->xywh;
|
||||
unsigned int h = xywh & 0x3;
|
||||
unsigned int w = (xywh & 0xC) >> 2;
|
||||
unsigned int y = (xywh & 0xFF0) >> 4;
|
||||
unsigned int x = (xywh & 0xF000) >> 12;
|
||||
switch(dir) {
|
||||
case 0: // Left
|
||||
x--;
|
||||
break;
|
||||
case 1: // Right
|
||||
x++;
|
||||
break;
|
||||
case 2: // Down
|
||||
y++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
block->xywh = (x << 12) | (y << 4) | (w << 2) | h;
|
||||
}
|
||||
|
||||
unsigned int move(struct block *block, int dir) {
|
||||
struct block moved;
|
||||
copy_block(&moved, block);
|
||||
block_move(&moved, dir);
|
||||
if (check_bounds(&moved) && check_collision(&moved)) {
|
||||
copy_block(block, &moved);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void block_rotate(struct block *block, unsigned int clock) {
|
||||
unsigned int xywh = block->xywh;
|
||||
unsigned int h = xywh & 0x3;
|
||||
unsigned int w = (xywh & 0xC) >> 2;
|
||||
unsigned int y = (xywh & 0xFF0) >> 4;
|
||||
unsigned int x = (xywh & 0xF000) >> 12;
|
||||
unsigned int xyhw = make_xywh(x, y, h, w);
|
||||
unsigned int shape[3] = {0, 0, 0};
|
||||
if (clock) {
|
||||
for (int r = 0; r <= h; ++r) {
|
||||
for (int c = 0; c <= w; ++c) {
|
||||
shape[c] = shape[c] | (get_shape(block, r, c) << (h - r));
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
for (int r = 0; r <= h; ++r) {
|
||||
for (int c = 0; c <= w; ++c) {
|
||||
shape[w - c] = shape[w - c] | (get_shape(block, r, c) << r);
|
||||
}
|
||||
}
|
||||
}
|
||||
block->shape[0] = shape[0];
|
||||
block->shape[1] = shape[1];
|
||||
block->shape[2] = shape[2];
|
||||
block->xywh = xyhw;
|
||||
}
|
||||
|
||||
|
||||
void rotate(struct block *block, int clock) {
|
||||
struct block rotated;
|
||||
copy_block(&rotated, block);
|
||||
block_rotate(&rotated, clock);
|
||||
if (check_bounds(&rotated) && check_collision(&rotated)) {
|
||||
copy_block(block, &rotated);
|
||||
return;
|
||||
}
|
||||
unsigned int xywh = rotated.xywh;
|
||||
unsigned int h = xywh & 0x3;
|
||||
unsigned int w = (xywh & 0xc) >> 2;
|
||||
unsigned int y = (xywh & 0xff0) >> 4;
|
||||
unsigned int x = (xywh & 0xf000) >> 12;
|
||||
if (x + w >= COLS) {
|
||||
x = COLS - w - 1;
|
||||
}
|
||||
rotated.xywh = make_xywh(x, y, w, h);
|
||||
if (check_bounds(&rotated) && check_collision(&rotated)) {
|
||||
copy_block(block, &rotated);
|
||||
}
|
||||
}
|
||||
|
||||
void clear_board() {
|
||||
for (int i = 0, s = wk_mul(ROWS, COLS); i < s; ++i) {
|
||||
board[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void fix_block(struct block *block) {
|
||||
unsigned int xywh = block->xywh;
|
||||
unsigned int h = xywh & 0x3;
|
||||
unsigned int w = (xywh & 0xc) >> 2;
|
||||
unsigned int y = (xywh & 0xff0) >> 4;
|
||||
unsigned int x = (xywh & 0xf000) >> 12;
|
||||
#ifdef DEBUG
|
||||
printf("%d %d %d %d\n", x, y, w, h);
|
||||
#endif
|
||||
for (int r = 0; r <= h; ++r) {
|
||||
for (int c = 0; c <= w; ++c) {
|
||||
if (get_shape(block, r, c)) {
|
||||
board[wk_mul(y + r, COLS) + x + c] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void print_score() {
|
||||
int c = 8;
|
||||
putch_at(c++, -2, 'S');
|
||||
putch_at(c++, -2, 'C');
|
||||
putch_at(c++, -2, 'O');
|
||||
putch_at(c++, -2, 'R');
|
||||
putch_at(c++, -2, 'E');
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
unsigned int mask = 0xF << (i * 4);
|
||||
unsigned int num = (score & mask) >> (i * 4);
|
||||
putch_at(12 - i, -1, num + '0');
|
||||
}
|
||||
}
|
||||
|
||||
void draw_board() {
|
||||
for (int r = 0; r < ROWS; ++r) {
|
||||
for (int c = 0; c < COLS; ++c) {
|
||||
if (board[wk_mul(r , COLS) + c] == 1) {
|
||||
putch_at((c << 1) + 1, r, '[');
|
||||
putch_at((c << 1) + 2, r, ']');
|
||||
} else {
|
||||
putch_at((c << 1) + 1, r, ' ');
|
||||
putch_at((c << 1)+ 2, r, ' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
unsigned int xywh = current.xywh;
|
||||
unsigned int h = xywh & 0x3;
|
||||
unsigned int w = (xywh & 0xc) >> 2;
|
||||
unsigned int y = (xywh & 0xff0) >> 4;
|
||||
unsigned int x = (xywh & 0xf000) >> 12;
|
||||
for (int r = 0; r <= h; ++r) {
|
||||
for (int c = 0; c <= w; ++c) {
|
||||
if (get_shape(¤t, r, c)) {
|
||||
putch_at(((c + x) << 1) + 1, r + y, '[');
|
||||
putch_at(((c + x) << 1) + 2, r + y, ']');
|
||||
}
|
||||
}
|
||||
}
|
||||
print_score();
|
||||
}
|
||||
|
||||
|
||||
void add_score(unsigned int delta) {
|
||||
score += delta;
|
||||
for (unsigned int i = 0, carry = 0; i < 32; i += 4) {
|
||||
unsigned int mask = 0xF << i;
|
||||
unsigned int num = (score & mask) >> i;
|
||||
num += carry;
|
||||
if (num >= 10) {
|
||||
carry = 1;
|
||||
num -= 10;
|
||||
} else {
|
||||
carry = 0;
|
||||
}
|
||||
score &= ~(mask);
|
||||
score |= (num << i);
|
||||
}
|
||||
}
|
||||
|
||||
void check_clear() {
|
||||
unsigned int y = (current.xywh & 0xff0) >> 4;
|
||||
unsigned int h = current.xywh & 0x3;
|
||||
for (int r = y + h; r >= y; --r) {
|
||||
unsigned int count = 0;
|
||||
for (int c = 0; c < COLS; ++c) {
|
||||
if (board[wk_mul(r , COLS) + c]) ++count;
|
||||
}
|
||||
if (count == COLS) {
|
||||
add_score(1);
|
||||
for (int nr = r - 1; nr > 0; --nr) {
|
||||
for (int c = 0; c < COLS; ++c) {
|
||||
board[wk_mul(nr + 1, COLS) + c] = board[wk_mul(nr, COLS) + c];
|
||||
}
|
||||
}
|
||||
++r; ++y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int rand() {
|
||||
static unsigned int seed = 990315;
|
||||
seed = (wk_mul(1103515245 , seed) + 12345) & 0x7FFFFFFF;
|
||||
return seed;
|
||||
}
|
||||
|
||||
unsigned int rand_type() {
|
||||
unsigned int type = rand() & 0x7;
|
||||
while (type == 7) {
|
||||
type = rand() & 0x7;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
void fall() {
|
||||
if (move(¤t, 2) == 0) {
|
||||
fix_block(¤t);
|
||||
check_clear();
|
||||
init_block(¤t, rand_type(), 4, 0);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void print_screen() {
|
||||
for (int r = 0; r < SCREEN_ROWS; ++r) {
|
||||
for (int c = 0; c < SCREEN_COLS; ++c) {
|
||||
printf("%c", screen[wk_mul(r, SCREEN_COLS) + c]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
void on_input(unsigned int ch) {
|
||||
switch (ch) {
|
||||
case 's':
|
||||
fall();
|
||||
break;
|
||||
case 'a':
|
||||
move(¤t, 0);
|
||||
break;
|
||||
case 'd':
|
||||
move(¤t, 1);
|
||||
break;
|
||||
case 'j':
|
||||
rotate(¤t, 0);
|
||||
break;
|
||||
case 'k':
|
||||
rotate(¤t, 1);
|
||||
break;
|
||||
}
|
||||
draw_board();
|
||||
#ifdef DEBUG
|
||||
print_screen();
|
||||
#endif
|
||||
}
|
||||
|
||||
void on_timer() {
|
||||
fall();
|
||||
draw_board();
|
||||
}
|
||||
|
||||
void trap_handler(void *epc, unsigned int cause) {
|
||||
if (cause == 0x80000007) {
|
||||
on_timer();
|
||||
} else {
|
||||
unsigned int ch = *UART_RECV;
|
||||
*UART_SEND = ch;
|
||||
on_input(ch);
|
||||
}
|
||||
}
|
||||
|
||||
void init() {
|
||||
clear_board();
|
||||
// Draw border
|
||||
for (int r = 0; r < ROWS; ++r) {
|
||||
putch_at(0, r, '|');
|
||||
putch_at(COLS << 1 | 1, r, '|');
|
||||
}
|
||||
for (int c = 0; c <= (COLS << 1 | 1); ++c) {
|
||||
putch_at(c, ROWS, '-');
|
||||
}
|
||||
int c = 8;
|
||||
putch_at(c++, ROWS + 1, 'T');
|
||||
putch_at(c++, ROWS + 1, 'E');
|
||||
putch_at(c++, ROWS + 1, 'T');
|
||||
putch_at(c++, ROWS + 1, 'R');
|
||||
putch_at(c++, ROWS + 1, 'I');
|
||||
putch_at(c++, ROWS + 1, 'S');
|
||||
c = 6;
|
||||
putch_at(c++, ROWS + 3, 'H');
|
||||
putch_at(c++, ROWS + 3, 'o');
|
||||
putch_at(c++, ROWS + 3, 'w');
|
||||
putch_at(c++, ROWS + 3, 'a');
|
||||
putch_at(c++, ROWS + 3, 'r');
|
||||
putch_at(c++, ROWS + 3, 'd');
|
||||
c++;
|
||||
putch_at(c++, ROWS + 3, 'L');
|
||||
putch_at(c++, ROWS + 3, 'a');
|
||||
putch_at(c++, ROWS + 3, 'u');
|
||||
c = 9;
|
||||
putch_at(c++, ROWS + 4, '2');
|
||||
putch_at(c++, ROWS + 4, '0');
|
||||
putch_at(c++, ROWS + 4, '2');
|
||||
putch_at(c++, ROWS + 4, '1');
|
||||
init_block(¤t, rand_type(), 4, 0);
|
||||
score = 0;
|
||||
draw_board();
|
||||
}
|
||||
|
||||
void clear_screen() {
|
||||
int *vram = ((int *) VRAM_BASE);
|
||||
for (int i = 0; i < 600; ++i) vram[i] = 0x20202020;
|
||||
}
|
||||
|
||||
extern void enable_interrupt();
|
||||
|
||||
int main() {
|
||||
#ifdef DEBUG
|
||||
unsigned char b[ROWS * COLS] = {0};
|
||||
board = b;
|
||||
for (int i = 0; i < SCREEN_ROWS * SCREEN_COLS; ++i) screen[i] = '%';
|
||||
init();
|
||||
#else
|
||||
board = (unsigned char *) 16384;
|
||||
for (int i = 0; i < 16384; i += 4) {
|
||||
*((int*) (board + i)) = 0;
|
||||
}
|
||||
clear_screen();
|
||||
init();
|
||||
*((unsigned int *) 4) = 0xDEADBEEF;
|
||||
enable_interrupt();
|
||||
*TIMER_ENABLED = 1;
|
||||
*TIMER_LIMIT = FALL_TIMER_LIMIT;
|
||||
for (;;);
|
||||
#endif
|
||||
#ifdef DEBUG
|
||||
on_input('a');
|
||||
on_input('a');
|
||||
on_input('s');
|
||||
on_input('s');
|
||||
on_input('s');
|
||||
for (int i = 21; i >= 0; --i) {
|
||||
on_timer();
|
||||
}
|
||||
on_input('d');
|
||||
on_input('d');
|
||||
on_input('d');
|
||||
on_input('d');
|
||||
for (int i = 21; i >= 0; --i) {
|
||||
on_timer();
|
||||
}
|
||||
on_input('d');
|
||||
on_input('d');
|
||||
on_input('d');
|
||||
on_input('d');
|
||||
on_input('d');
|
||||
for (int i = 21; i >= 0; --i) {
|
||||
on_timer();
|
||||
add_score(10);
|
||||
}
|
||||
print_score();
|
||||
print_screen();
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
20
lab1/csrc/toolchain.cmake
Normal file
20
lab1/csrc/toolchain.cmake
Normal file
@@ -0,0 +1,20 @@
|
||||
set(CMAKE_SYSTEM_NAME Generic)
|
||||
set(CMAKE_SYSTEM_PROCESSOR riscv32)
|
||||
|
||||
set(triple riscv32-unknown-elf)
|
||||
|
||||
set(CMAKE_C_COMPILER clang)
|
||||
set(CMAKE_C_COMPILER_TARGET ${triple})
|
||||
set(CMAKE_CXX_COMPILER clang++)
|
||||
set(CMAKE_CXX_COMPILER_TARGET ${triple})
|
||||
set(CMAKE_ASM_COMPILER clang)
|
||||
set(CMAKE_ASM_COMPILER_TARGET ${triple})
|
||||
set(CMAKE_AR llvm-ar CACHE FILEPATH "Archiver")
|
||||
set(CMAKE_OBJCOPY llvm-objcopy)
|
||||
|
||||
set(CMAKE_C_FLAGS_INIT "-mno-relax")
|
||||
set(CMAKE_CXX_FLAGS_INIT "-mno-relax")
|
||||
set(CMAKE_ASM_FLAGS_INIT "-mno-relax")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_INIT "-fuse-ld=lld -nostdlib -static -mno-relax")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS_INIT "-fuse-ld=lld -nostdlib -static -mno-relax")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_INIT "-fuse-ld=lld -nostdlib -static -mno-relax")
|
||||
1
lab1/project/build.properties
Normal file
1
lab1/project/build.properties
Normal file
@@ -0,0 +1 @@
|
||||
sbt.version = 1.9.6
|
||||
1
lab1/project/plugins.sbt
Normal file
1
lab1/project/plugins.sbt
Normal file
@@ -0,0 +1 @@
|
||||
logLevel := Level.Warn
|
||||
7
lab1/riscv-target/yatcpu/Makefile.include
Normal file
7
lab1/riscv-target/yatcpu/Makefile.include
Normal file
@@ -0,0 +1,7 @@
|
||||
export TARGETDIR ?= riscv-target
|
||||
export XLEN = 32
|
||||
export RISCV_TARGET = yatcpu
|
||||
export RISCV_DEVICE =
|
||||
export RISCV_TARGET_FLAGS =
|
||||
export RISCV_ASSERT = 0
|
||||
JOBS = -j1
|
||||
54
lab1/riscv-target/yatcpu/device/rv32i_m/I/Makefile.include
Normal file
54
lab1/riscv-target/yatcpu/device/rv32i_m/I/Makefile.include
Normal file
@@ -0,0 +1,54 @@
|
||||
TARGET_SIM ?= verilog/verilator/obj_dir/VTop
|
||||
TARGET_FLAGS ?= $(RISCV_TARGET_FLAGS)
|
||||
ifeq ($(shell command -v $(TARGET_SIM) 2> /dev/null),)
|
||||
$(error Target simulator executable '$(TARGET_SIM)` not found)
|
||||
endif
|
||||
|
||||
RISCV_PREFIX ?= riscv64-unknown-elf-
|
||||
RISCV_GCC ?= $(RISCV_PREFIX)gcc
|
||||
RISCV_OBJDUMP ?= $(RISCV_PREFIX)objdump
|
||||
RISCV_OBJCOPY ?= $(RISCV_PREFIX)objcopy
|
||||
RISCV_GCC_OPTS ?= -g -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles $(RVTEST_DEFINES)
|
||||
|
||||
COMPILE_CMD = $$(RISCV_GCC) $(1) $$(RISCV_GCC_OPTS) \
|
||||
-I$(ROOTDIR)/riscv-test-suite/env/ \
|
||||
-I$(TARGETDIR)/$(RISCV_TARGET)/ \
|
||||
-T$(TARGETDIR)/$(RISCV_TARGET)/link.ld \
|
||||
$$(<) -o $$@
|
||||
|
||||
OBJDUMP_CMD = $$(RISCV_OBJDUMP) $$@ -D > $$@.objdump; \
|
||||
$$(RISCV_OBJDUMP) $$@ --source > $$@.debug; \
|
||||
$$(RISCV_OBJDUMP) -t $$@ | grep " begin_signature$$$$" | awk '{ print $$$$1 }' > $$@.begin_signature; \
|
||||
$$(RISCV_OBJDUMP) -t $$@ | grep " end_signature$$$$" | awk '{ print $$$$1 }' > $$@.end_signature; \
|
||||
$$(RISCV_OBJDUMP) -t $$@ | grep " tohost$$$$" | awk '{ print $$$$1 }' > $$@.halt \
|
||||
|
||||
|
||||
OBJCOPY_CMD = $$(RISCV_OBJCOPY) $$@ -O binary -j .text -j .data -j .tohost $$@.asmbin
|
||||
|
||||
COMPILE_TARGET=\
|
||||
$(COMPILE_CMD); \
|
||||
if [ $$$$? -ne 0 ] ; \
|
||||
then \
|
||||
echo "\e[31m$$(RISCV_GCC) failed for target $$(@) \e[39m" ; \
|
||||
exit 1 ; \
|
||||
fi ; \
|
||||
$(OBJDUMP_CMD); \
|
||||
if [ $$$$? -ne 0 ] ; \
|
||||
then \
|
||||
echo "\e[31m $$(RISCV_OBJDUMP) failed for target $$(@) \e[39m" ; \
|
||||
exit 1 ; \
|
||||
fi ; \
|
||||
$(OBJCOPY_CMD); \
|
||||
if [ $$$$? -ne 0 ] ; \
|
||||
then \
|
||||
echo "\e[31m $$(RISCV_OBJCOPY) failed for target $$(@) \e[39m" ; \
|
||||
exit 1 ; \
|
||||
fi ; \
|
||||
|
||||
RUN_CMD = $(TARGET_SIM) $(TARGET_FLAGS) \
|
||||
-signature 0x$(shell cat $(<).begin_signature) 0x$(shell cat $(<).end_signature) $(*).signature.output \
|
||||
-halt 0x$(shell cat $(<).halt) \
|
||||
-time 1000000 \
|
||||
-instruction $(<).asmbin
|
||||
RUN_TARGET = \
|
||||
$(RUN_CMD)
|
||||
12
lab1/riscv-target/yatcpu/link.ld
Normal file
12
lab1/riscv-target/yatcpu/link.ld
Normal file
@@ -0,0 +1,12 @@
|
||||
OUTPUT_ARCH( "riscv" )
|
||||
ENTRY(rvtest_entry_point)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x00001000;
|
||||
.text : { *(.text.init) *(.text.startup) *(.text) }
|
||||
.data ALIGN(0x1000) : { *(.data*) *(.rodata*) *(.sdata*) }
|
||||
.tohost ALIGN(0x1000) : { *(.tohost) }
|
||||
.bss : { *(.bss) }
|
||||
_end = .;
|
||||
}
|
||||
46
lab1/riscv-target/yatcpu/model_test.h
Normal file
46
lab1/riscv-target/yatcpu/model_test.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#ifndef _COMPLIANCE_MODEL_H_
|
||||
#define _COMPLIANCE_MODEL_H_
|
||||
|
||||
#define ALIGNMENT 2
|
||||
|
||||
#define RVMODEL_DATA_SECTION \
|
||||
.pushsection .tohost,"aw",@progbits; \
|
||||
.align 4; .global tohost; tohost: .word 0; \
|
||||
.popsection;
|
||||
|
||||
#define RVMODEL_BOOT
|
||||
|
||||
#define RVMODEL_HALT \
|
||||
li x1, 0xBABECAFE; \
|
||||
write_tohost: \
|
||||
sw x1, tohost, x0; \
|
||||
loop: j loop
|
||||
|
||||
//RV_COMPLIANCE_DATA_BEGIN
|
||||
#define RVMODEL_DATA_BEGIN \
|
||||
.align 4; .global begin_signature; begin_signature:
|
||||
|
||||
//RV_COMPLIANCE_DATA_END
|
||||
#define RVMODEL_DATA_END \
|
||||
.align 4; .global end_signature; end_signature: \
|
||||
RVMODEL_DATA_SECTION \
|
||||
|
||||
//RVTEST_IO_INIT
|
||||
#define RVMODEL_IO_INIT
|
||||
//RVTEST_IO_WRITE_STR
|
||||
#define RVMODEL_IO_WRITE_STR(_R, _STR)
|
||||
//RVTEST_IO_CHECK
|
||||
#define RVMODEL_IO_CHECK()
|
||||
//RVTEST_IO_ASSERT_GPR_EQ
|
||||
#define RVMODEL_IO_ASSERT_GPR_EQ(_S, _R, _I)
|
||||
//RVTEST_IO_ASSERT_SFPR_EQ
|
||||
#define RVMODEL_IO_ASSERT_SFPR_EQ(_F, _R, _I)
|
||||
//RVTEST_IO_ASSERT_DFPR_EQ
|
||||
#define RVMODEL_IO_ASSERT_DFPR_EQ(_D, _R, _I)
|
||||
|
||||
#define RVMODEL_SET_MSW_INT
|
||||
#define RVMODEL_CLEAR_MSW_INT
|
||||
#define RVMODEL_CLEAR_MTIMER_INT
|
||||
#define RVMODEL_CLEAR_MEXT_INT
|
||||
|
||||
#endif
|
||||
BIN
lab1/src/main/resources/fibonacci.asmbin
Normal file
BIN
lab1/src/main/resources/fibonacci.asmbin
Normal file
Binary file not shown.
BIN
lab1/src/main/resources/hello.asmbin
Normal file
BIN
lab1/src/main/resources/hello.asmbin
Normal file
Binary file not shown.
BIN
lab1/src/main/resources/litenes.asmbin
Normal file
BIN
lab1/src/main/resources/litenes.asmbin
Normal file
Binary file not shown.
BIN
lab1/src/main/resources/mmio.asmbin
Normal file
BIN
lab1/src/main/resources/mmio.asmbin
Normal file
Binary file not shown.
BIN
lab1/src/main/resources/quicksort.asmbin
Normal file
BIN
lab1/src/main/resources/quicksort.asmbin
Normal file
Binary file not shown.
BIN
lab1/src/main/resources/sb.asmbin
Normal file
BIN
lab1/src/main/resources/sb.asmbin
Normal file
Binary file not shown.
BIN
lab1/src/main/resources/tetris.asmbin
Normal file
BIN
lab1/src/main/resources/tetris.asmbin
Normal file
Binary file not shown.
BIN
lab1/src/main/resources/vga_font_8x16.bmp
Normal file
BIN
lab1/src/main/resources/vga_font_8x16.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
54
lab1/src/main/scala/board/basys3/BCD2Segments.scala
Normal file
54
lab1/src/main/scala/board/basys3/BCD2Segments.scala
Normal file
@@ -0,0 +1,54 @@
|
||||
// Copyright 2021 Howard Lau
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package board.basys3
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
|
||||
class BCD2Segments extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val bcd = Input(UInt(4.W))
|
||||
val segs = Output(UInt(8.W))
|
||||
})
|
||||
|
||||
val bcd = io.bcd
|
||||
val segs = Wire(UInt(8.W))
|
||||
|
||||
segs := MuxLookup(
|
||||
bcd,
|
||||
0xFF.U,
|
||||
IndexedSeq(
|
||||
0.U -> "b10000001".U,
|
||||
1.U -> "b11001111".U,
|
||||
2.U -> "b10010010".U,
|
||||
3.U -> "b10000110".U,
|
||||
4.U -> "b11001100".U,
|
||||
5.U -> "b10100100".U,
|
||||
6.U -> "b10100000".U,
|
||||
7.U -> "b10001111".U,
|
||||
8.U -> "b10000000".U,
|
||||
9.U -> "b10000100".U,
|
||||
10.U -> "b00001000".U,
|
||||
11.U -> "b01100000".U,
|
||||
12.U -> "b00110001".U,
|
||||
13.U -> "b01000010".U,
|
||||
14.U -> "b00110000".U,
|
||||
15.U -> "b00111000".U,
|
||||
)
|
||||
)
|
||||
|
||||
io.segs := segs
|
||||
}
|
||||
|
||||
32
lab1/src/main/scala/board/basys3/OnboardDigitDisplay.scala
Normal file
32
lab1/src/main/scala/board/basys3/OnboardDigitDisplay.scala
Normal file
@@ -0,0 +1,32 @@
|
||||
// Copyright 2021 Howard Lau
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package board.basys3
|
||||
|
||||
import chisel3._
|
||||
|
||||
class OnboardDigitDisplay extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val digit_mask = Output(UInt(4.W))
|
||||
})
|
||||
|
||||
val counter = RegInit(UInt(16.W), 0.U)
|
||||
val digit_mask = RegInit(UInt(4.W), "b0111".U)
|
||||
|
||||
counter := counter + 1.U
|
||||
when(counter === 0.U) {
|
||||
digit_mask := (digit_mask << 1.U).asUInt + digit_mask(3)
|
||||
}
|
||||
io.digit_mask := digit_mask
|
||||
}
|
||||
34
lab1/src/main/scala/board/basys3/SYSULogo.scala
Normal file
34
lab1/src/main/scala/board/basys3/SYSULogo.scala
Normal file
@@ -0,0 +1,34 @@
|
||||
// Copyright 2021 Howard Lau
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package board.basys3
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
|
||||
class SYSULogo extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val digit_mask = Input(UInt(4.W))
|
||||
val segs = Output(UInt(8.W))
|
||||
})
|
||||
|
||||
io.segs := MuxLookup(
|
||||
io.digit_mask,
|
||||
"b00100100".U, // "b0111".U, "b1101".U -> S
|
||||
IndexedSeq(
|
||||
"b1011".U -> "b01000100".U, // Y
|
||||
"b1110".U -> "b01000001".U, // U
|
||||
)
|
||||
)
|
||||
}
|
||||
42
lab1/src/main/scala/board/basys3/SegmentMux.scala
Normal file
42
lab1/src/main/scala/board/basys3/SegmentMux.scala
Normal file
@@ -0,0 +1,42 @@
|
||||
// Copyright 2021 Howard Lau
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package board.basys3
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
|
||||
class SegmentMux extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val digit_mask = Input(UInt(4.W))
|
||||
val numbers = Input(UInt(16.W))
|
||||
val segs = Output(UInt(8.W))
|
||||
})
|
||||
|
||||
|
||||
val digit = RegInit(UInt(4.W), 0.U)
|
||||
val bcd2segs = Module(new BCD2Segments)
|
||||
|
||||
bcd2segs.io.bcd := digit
|
||||
io.segs := bcd2segs.io.segs
|
||||
digit := MuxLookup(
|
||||
io.digit_mask,
|
||||
io.numbers(3, 0), // "b1110".U
|
||||
IndexedSeq(
|
||||
"b1101".U -> io.numbers(7, 4),
|
||||
"b1011".U -> io.numbers(11, 8),
|
||||
"b0111".U -> io.numbers(15, 12)
|
||||
)
|
||||
)
|
||||
}
|
||||
123
lab1/src/main/scala/board/basys3/Top.scala
Normal file
123
lab1/src/main/scala/board/basys3/Top.scala
Normal file
@@ -0,0 +1,123 @@
|
||||
// Copyright 2021 Howard Lau
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package board.basys3
|
||||
|
||||
import chisel3._
|
||||
import chisel3.experimental.ChiselEnum
|
||||
import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage}
|
||||
import chisel3.util._
|
||||
import peripheral.{CharacterDisplay, Dummy, InstructionROM, Memory, ROMLoader, VGADisplay}
|
||||
import riscv._
|
||||
import riscv.core.{CPU, ProgramCounter}
|
||||
|
||||
object BootStates extends ChiselEnum {
|
||||
val Init, Loading, Finished = Value
|
||||
}
|
||||
|
||||
class Top extends Module {
|
||||
val binaryFilename = "tetris.asmbin"
|
||||
val io = IO(new Bundle {
|
||||
val switch = Input(UInt(16.W))
|
||||
|
||||
val segs = Output(UInt(8.W))
|
||||
val digit_mask = Output(UInt(4.W))
|
||||
|
||||
val hsync = Output(Bool())
|
||||
val vsync = Output(Bool())
|
||||
val rgb = Output(UInt(12.W))
|
||||
val led = Output(UInt(16.W))
|
||||
|
||||
})
|
||||
val vga_display = Module(new VGADisplay)
|
||||
val display = Module(new CharacterDisplay)
|
||||
|
||||
val mem = Module(new Memory(Parameters.MemorySizeInWords))
|
||||
val dummy = Module(new Dummy)
|
||||
|
||||
display.io.bundle <> dummy.io.bundle
|
||||
mem.io.bundle <> dummy.io.bundle
|
||||
mem.io.debug_read_address := 0.U
|
||||
|
||||
val instruction_rom = Module(new InstructionROM(binaryFilename))
|
||||
val rom_loader = Module(new ROMLoader(instruction_rom.capacity))
|
||||
|
||||
rom_loader.io.rom_data := instruction_rom.io.data
|
||||
rom_loader.io.load_address := Parameters.EntryAddress
|
||||
instruction_rom.io.address := rom_loader.io.rom_address
|
||||
|
||||
val CPU_clkdiv = RegInit(UInt(2.W), 0.U)
|
||||
val CPU_tick = Wire(Bool())
|
||||
val CPU_next = Wire(UInt(2.W))
|
||||
CPU_next := Mux(CPU_clkdiv === 3.U, 0.U, CPU_clkdiv + 1.U)
|
||||
CPU_tick := CPU_clkdiv === 0.U
|
||||
CPU_clkdiv := CPU_next
|
||||
|
||||
withClock(CPU_tick.asClock) {
|
||||
val cpu = Module(new CPU)
|
||||
cpu.io.debug_read_address := 0.U
|
||||
cpu.io.instruction_valid := rom_loader.io.load_finished
|
||||
mem.io.instruction_address := cpu.io.instruction_address
|
||||
cpu.io.instruction := mem.io.instruction
|
||||
|
||||
when(!rom_loader.io.load_finished) {
|
||||
rom_loader.io.bundle <> mem.io.bundle
|
||||
cpu.io.memory_bundle.read_data := 0.U
|
||||
}.otherwise {
|
||||
rom_loader.io.bundle.read_data := 0.U
|
||||
when(cpu.io.deviceSelect === 1.U) {
|
||||
cpu.io.memory_bundle <> display.io.bundle
|
||||
}.otherwise {
|
||||
cpu.io.memory_bundle <> mem.io.bundle
|
||||
}
|
||||
}
|
||||
}
|
||||
io.hsync := vga_display.io.hsync
|
||||
io.vsync := vga_display.io.vsync
|
||||
|
||||
display.io.x := vga_display.io.x
|
||||
display.io.y := vga_display.io.y
|
||||
display.io.video_on := vga_display.io.video_on
|
||||
|
||||
io.rgb := display.io.rgb
|
||||
|
||||
mem.io.debug_read_address := io.switch(15, 1).asUInt << 2
|
||||
io.led := Mux(
|
||||
io.switch(0),
|
||||
mem.io.debug_read_data(31, 16).asUInt,
|
||||
mem.io.debug_read_data(15, 0).asUInt,
|
||||
)
|
||||
|
||||
val onboard_display = Module(new OnboardDigitDisplay)
|
||||
io.digit_mask := onboard_display.io.digit_mask
|
||||
|
||||
val sysu_logo = Module(new SYSULogo)
|
||||
sysu_logo.io.digit_mask := io.digit_mask
|
||||
|
||||
val seg_mux = Module(new SegmentMux)
|
||||
seg_mux.io.digit_mask := io.digit_mask
|
||||
seg_mux.io.numbers := io.led
|
||||
|
||||
io.segs := MuxLookup(
|
||||
io.switch,
|
||||
seg_mux.io.segs,
|
||||
IndexedSeq(
|
||||
0.U -> sysu_logo.io.segs
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
object VerilogGenerator extends App {
|
||||
(new ChiselStage).execute(Array("-X", "verilog", "-td", "verilog/basys3"), Seq(ChiselGeneratorAnnotation(() => new Top)))
|
||||
}
|
||||
93
lab1/src/main/scala/board/pynq/Top.scala
Normal file
93
lab1/src/main/scala/board/pynq/Top.scala
Normal file
@@ -0,0 +1,93 @@
|
||||
// Copyright 2022 Canbin Huang
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package board.pynq
|
||||
|
||||
import chisel3._
|
||||
import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage}
|
||||
import peripheral._
|
||||
import riscv.Parameters
|
||||
import riscv.core.{CPU, ProgramCounter}
|
||||
|
||||
class Top extends Module {
|
||||
val binaryFilename = "hello.asmbin"
|
||||
val io = IO(new Bundle() {
|
||||
val hdmi_clk_n = Output(Bool())
|
||||
val hdmi_clk_p = Output(Bool())
|
||||
val hdmi_data_n = Output(UInt(3.W))
|
||||
val hdmi_data_p = Output(UInt(3.W))
|
||||
val hdmi_hpdn = Output(Bool())
|
||||
|
||||
val led = Output(UInt(4.W))
|
||||
})
|
||||
val hdmi_display = Module(new HDMIDisplay)
|
||||
val display = Module(new CharacterDisplay)
|
||||
val mem = Module(new Memory(Parameters.MemorySizeInWords))
|
||||
val dummy = Module(new Dummy)
|
||||
|
||||
display.io.bundle <> dummy.io.bundle
|
||||
mem.io.bundle <> dummy.io.bundle
|
||||
mem.io.debug_read_address := 0.U
|
||||
|
||||
val instruction_rom = Module(new InstructionROM(binaryFilename))
|
||||
val rom_loader = Module(new ROMLoader(instruction_rom.capacity))
|
||||
|
||||
rom_loader.io.rom_data := instruction_rom.io.data
|
||||
rom_loader.io.load_address := Parameters.EntryAddress
|
||||
instruction_rom.io.address := rom_loader.io.rom_address
|
||||
|
||||
val CPU_clkdiv = RegInit(UInt(2.W),0.U)
|
||||
val CPU_tick = Wire(Bool())
|
||||
val CPU_next = Wire(UInt(2.W))
|
||||
CPU_next := Mux(CPU_clkdiv === 3.U, 0.U, CPU_clkdiv + 1.U)
|
||||
CPU_tick := CPU_clkdiv === 0.U
|
||||
CPU_clkdiv := CPU_next
|
||||
|
||||
withClock(CPU_tick.asClock) {
|
||||
val cpu = Module(new CPU)
|
||||
cpu.io.debug_read_address := 0.U
|
||||
cpu.io.instruction_valid := rom_loader.io.load_finished
|
||||
mem.io.instruction_address := cpu.io.instruction_address
|
||||
cpu.io.instruction := mem.io.instruction
|
||||
|
||||
when(!rom_loader.io.load_finished) {
|
||||
rom_loader.io.bundle <> mem.io.bundle
|
||||
cpu.io.memory_bundle.read_data := 0.U
|
||||
}.otherwise {
|
||||
rom_loader.io.bundle.read_data := 0.U
|
||||
when(cpu.io.deviceSelect === 1.U) {
|
||||
cpu.io.memory_bundle <> display.io.bundle
|
||||
}.otherwise {
|
||||
cpu.io.memory_bundle <> mem.io.bundle
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
io.led := 15.U(4.W)
|
||||
|
||||
display.io.x := hdmi_display.io.x
|
||||
display.io.y := hdmi_display.io.y
|
||||
display.io.video_on := hdmi_display.io.video_on
|
||||
hdmi_display.io.rgb := display.io.rgb
|
||||
|
||||
io.hdmi_hpdn := 1.U
|
||||
io.hdmi_data_n := hdmi_display.io.TMDSdata_n
|
||||
io.hdmi_data_p := hdmi_display.io.TMDSdata_p
|
||||
io.hdmi_clk_n := hdmi_display.io.TMDSclk_n
|
||||
io.hdmi_clk_p := hdmi_display.io.TMDSclk_p
|
||||
}
|
||||
|
||||
object VerilogGenerator extends App {
|
||||
(new ChiselStage).execute(Array("-X", "verilog", "-td", "verilog/pynq"), Seq(ChiselGeneratorAnnotation(() => new Top)))
|
||||
}
|
||||
43
lab1/src/main/scala/board/verilator/Top.scala
Normal file
43
lab1/src/main/scala/board/verilator/Top.scala
Normal file
@@ -0,0 +1,43 @@
|
||||
// Copyright 2022 Canbin Huang
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package board.verilator
|
||||
|
||||
import chisel3._
|
||||
import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage}
|
||||
import peripheral._
|
||||
import riscv.{CPUBundle, Parameters}
|
||||
import riscv.core.CPU
|
||||
|
||||
class Top extends Module {
|
||||
val io = IO(new CPUBundle)
|
||||
|
||||
val cpu = Module(new CPU)
|
||||
|
||||
io.deviceSelect := 0.U
|
||||
cpu.io.debug_read_address := io.debug_read_address
|
||||
io.debug_read_data := cpu.io.debug_read_data
|
||||
|
||||
io.memory_bundle <> cpu.io.memory_bundle
|
||||
io.instruction_address := cpu.io.instruction_address
|
||||
cpu.io.instruction := io.instruction
|
||||
|
||||
cpu.io.instruction_valid := io.instruction_valid
|
||||
|
||||
}
|
||||
|
||||
object VerilogGenerator extends App {
|
||||
(new ChiselStage).execute(Array("-X", "verilog", "-td", "verilog/verilator"), Seq(ChiselGeneratorAnnotation(() =>
|
||||
new Top())))
|
||||
}
|
||||
84
lab1/src/main/scala/peripheral/CharacterDisplay.scala
Normal file
84
lab1/src/main/scala/peripheral/CharacterDisplay.scala
Normal file
@@ -0,0 +1,84 @@
|
||||
// Copyright 2022 Howard Lau
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package peripheral
|
||||
|
||||
import chisel3.util.{MuxLookup, log2Up}
|
||||
import chisel3.{Bool, Bundle, Module, Mux, Output, UInt, Wire, _}
|
||||
import peripheral.ScreenInfo.{DisplayHorizontal, DisplayVertical}
|
||||
import riscv.Parameters
|
||||
|
||||
object GlyphInfo {
|
||||
val glyphWidth = 8
|
||||
val glyphHeight = 16
|
||||
// ASCII printable characters start from here
|
||||
val spaceIndex = 1
|
||||
}
|
||||
|
||||
object ScreenInfo {
|
||||
val DisplayHorizontal = 640
|
||||
val DisplayVertical = 480
|
||||
}
|
||||
|
||||
object CharacterBufferInfo {
|
||||
val CharCols = DisplayHorizontal / GlyphInfo.glyphWidth
|
||||
val CharRows = DisplayVertical / GlyphInfo.glyphHeight
|
||||
val Chars = CharCols * CharRows
|
||||
}
|
||||
|
||||
class CharacterDisplay extends Module {
|
||||
val io = IO(new Bundle() {
|
||||
val bundle = new RAMBundle()
|
||||
|
||||
val x = Input(UInt(16.W))
|
||||
val y = Input(UInt(16.W))
|
||||
val video_on = Input(Bool())
|
||||
|
||||
val rgb = Output(UInt(24.W))
|
||||
})
|
||||
|
||||
val mem = Module(new BlockRAM(CharacterBufferInfo.Chars / Parameters.WordSize))
|
||||
mem.io.write_enable := io.bundle.write_enable
|
||||
mem.io.write_data := io.bundle.write_data
|
||||
mem.io.write_address := io.bundle.address
|
||||
mem.io.write_strobe := io.bundle.write_strobe
|
||||
mem.io.read_address := io.bundle.address
|
||||
io.bundle.read_data := mem.io.read_data
|
||||
|
||||
|
||||
val font_rom = Module(new FontROM)
|
||||
val row = (io.y >> log2Up(GlyphInfo.glyphHeight)).asUInt
|
||||
val col = (io.x >> log2Up(GlyphInfo.glyphWidth)).asUInt
|
||||
val char_index = (row * CharacterBufferInfo.CharCols.U) + col
|
||||
val offset = char_index(1, 0)
|
||||
val ch = Wire(UInt(8.W))
|
||||
|
||||
mem.io.debug_read_address := char_index
|
||||
ch := MuxLookup(
|
||||
offset,
|
||||
0.U,
|
||||
IndexedSeq(
|
||||
0.U -> mem.io.debug_read_data(7, 0).asUInt,
|
||||
1.U -> mem.io.debug_read_data(15, 8).asUInt,
|
||||
2.U -> mem.io.debug_read_data(23, 16).asUInt,
|
||||
3.U -> mem.io.debug_read_data(31, 24).asUInt
|
||||
)
|
||||
)
|
||||
font_rom.io.glyph_index := Mux(ch >= 32.U, ch - 31.U, 0.U)
|
||||
font_rom.io.glyph_y := io.y(log2Up(GlyphInfo.glyphHeight) - 1, 0)
|
||||
|
||||
// White if pixel_on and glyph pixel on
|
||||
val glyph_x = io.x(log2Up(GlyphInfo.glyphWidth) - 1, 0)
|
||||
io.rgb := Mux(io.video_on && font_rom.io.glyph_pixel_byte(glyph_x), 0xFFFFFF.U, 0.U)
|
||||
}
|
||||
29
lab1/src/main/scala/peripheral/Dummy.scala
Normal file
29
lab1/src/main/scala/peripheral/Dummy.scala
Normal file
@@ -0,0 +1,29 @@
|
||||
// Copyright 2021 Howard Lau
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package peripheral
|
||||
|
||||
import chisel3._
|
||||
import riscv.Parameters
|
||||
|
||||
// A dummy master that never initiates reads or writes
|
||||
class Dummy extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val bundle = Flipped(new RAMBundle)
|
||||
})
|
||||
io.bundle.write_strobe := VecInit(Seq.fill(Parameters.WordSize)(false.B))
|
||||
io.bundle.write_data := 0.U
|
||||
io.bundle.write_enable := false.B
|
||||
io.bundle.address := 0.U
|
||||
}
|
||||
64
lab1/src/main/scala/peripheral/FontROM.scala
Normal file
64
lab1/src/main/scala/peripheral/FontROM.scala
Normal file
@@ -0,0 +1,64 @@
|
||||
package peripheral
|
||||
|
||||
import chisel3.experimental.{ChiselAnnotation, annotate}
|
||||
import chisel3.util.experimental.loadMemoryFromFileInline
|
||||
import chisel3.{Bundle, Input, Module, Output, SyncReadMem, UInt, _}
|
||||
import firrtl.annotations.MemorySynthInit
|
||||
|
||||
import java.io.FileWriter
|
||||
import java.nio.file.Paths
|
||||
import javax.imageio.ImageIO
|
||||
|
||||
class FontROM(fontBitmapFilename: String = "vga_font_8x16.bmp") extends Module {
|
||||
val glyphWidth = GlyphInfo.glyphWidth
|
||||
val glyphHeight = GlyphInfo.glyphHeight
|
||||
|
||||
val io = IO(new Bundle {
|
||||
val glyph_index = Input(UInt(7.W))
|
||||
val glyph_y = Input(UInt(4.W))
|
||||
|
||||
val glyph_pixel_byte = Output(UInt(8.W))
|
||||
})
|
||||
|
||||
annotate(new ChiselAnnotation {
|
||||
override def toFirrtl =
|
||||
MemorySynthInit
|
||||
})
|
||||
|
||||
val (hexTxtPath, glyphCount) = readFontBitmap()
|
||||
val mem = SyncReadMem(glyphCount, UInt(8.W))
|
||||
loadMemoryFromFileInline(mem, hexTxtPath.toString.replaceAll("\\\\", "/"))
|
||||
io.glyph_pixel_byte := mem.read(io.glyph_index * GlyphInfo.glyphHeight.U + io.glyph_y, true.B)
|
||||
|
||||
def readFontBitmap() = {
|
||||
val inputStream = getClass.getClassLoader.getResourceAsStream(fontBitmapFilename)
|
||||
val image = ImageIO.read(inputStream)
|
||||
|
||||
val glyphColumns = image.getWidth() / glyphWidth
|
||||
val glyphRows = image.getHeight / glyphHeight
|
||||
val glyphCount = glyphColumns * glyphRows
|
||||
val glyphs = new Array[UInt](glyphCount * GlyphInfo.glyphHeight)
|
||||
|
||||
for (row <- 0 until glyphRows) {
|
||||
for (col <- 0 until glyphColumns) {
|
||||
for (i <- 0 until glyphHeight) {
|
||||
var lineInt = 0
|
||||
for (j <- 0 until glyphWidth) {
|
||||
if (image.getRGB(col * glyphWidth + j, row * glyphHeight + i) != 0xFFFFFFFF) {
|
||||
lineInt |= (1 << j)
|
||||
}
|
||||
}
|
||||
glyphs((row * glyphColumns + col) * GlyphInfo.glyphHeight + i) = lineInt.U(8.W)
|
||||
}
|
||||
}
|
||||
}
|
||||
val currentDir = System.getProperty("user.dir")
|
||||
val hexTxtPath = Paths.get(currentDir, "verilog", f"${fontBitmapFilename}.txt")
|
||||
val writer = new FileWriter(hexTxtPath.toString)
|
||||
for (i <- glyphs.indices) {
|
||||
writer.write(f"@$i%x\n${glyphs(i).litValue}%02x\n")
|
||||
}
|
||||
writer.close()
|
||||
(hexTxtPath, glyphs.length)
|
||||
}
|
||||
}
|
||||
394
lab1/src/main/scala/peripheral/HDMIDisplay.scala
Normal file
394
lab1/src/main/scala/peripheral/HDMIDisplay.scala
Normal file
@@ -0,0 +1,394 @@
|
||||
// Copyright 2022 hrpccs
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package peripheral
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
|
||||
class HDMISync extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val hsync = Output(Bool())
|
||||
val vsync = Output(Bool())
|
||||
val video_on = Output(Bool())
|
||||
val p_tick = Output(Bool())
|
||||
val f_tick = Output(Bool())
|
||||
val x = Output(UInt(10.W))
|
||||
val y = Output(UInt(10.W))
|
||||
val x_next = Output(UInt(10.W))
|
||||
val y_next = Output(UInt(10.W))
|
||||
})
|
||||
|
||||
val DisplayHorizontal = ScreenInfo.DisplayHorizontal
|
||||
val DisplayVertical = ScreenInfo.DisplayVertical
|
||||
|
||||
val BorderLeft = 48
|
||||
val BorderRight = 16
|
||||
val BorderTop = 10
|
||||
val BorderBottom = 33
|
||||
|
||||
val RetraceHorizontal = 96
|
||||
val RetraceVertical = 2
|
||||
|
||||
val MaxHorizontal = DisplayHorizontal + BorderLeft + BorderRight + RetraceHorizontal - 1
|
||||
val MaxVertical = DisplayVertical + BorderTop + BorderBottom + RetraceVertical - 1
|
||||
|
||||
val RetraceHorizontalStart = DisplayHorizontal + BorderRight
|
||||
val RetraceHorizontalEnd = RetraceHorizontalStart + RetraceHorizontal - 1
|
||||
|
||||
val RetraceVerticalStart = DisplayVertical + BorderBottom
|
||||
val RetraceVerticalEnd = RetraceVerticalStart + RetraceVertical - 1
|
||||
|
||||
val pixel = RegInit(UInt(3.W), 0.U)
|
||||
val pixel_next = Wire(UInt(3.W))
|
||||
val pixel_tick = Wire(Bool())
|
||||
|
||||
val v_count_reg = RegInit(UInt(10.W), 0.U)
|
||||
val h_count_reg = RegInit(UInt(10.W), 0.U)
|
||||
|
||||
val v_count_next = Wire(UInt(10.W))
|
||||
val h_count_next = Wire(UInt(10.W))
|
||||
|
||||
val vsync_reg = RegInit(Bool(), false.B)
|
||||
val hsync_reg = RegInit(Bool(), false.B)
|
||||
|
||||
val vsync_next = Wire(Bool())
|
||||
val hsync_next = Wire(Bool())
|
||||
|
||||
pixel_next := Mux(pixel === 4.U, 0.U, pixel + 1.U)
|
||||
pixel_tick := pixel === 0.U
|
||||
|
||||
h_count_next := Mux(
|
||||
pixel_tick,
|
||||
Mux(h_count_reg === MaxHorizontal.U, 0.U, h_count_reg + 1.U),
|
||||
h_count_reg
|
||||
)
|
||||
|
||||
v_count_next := Mux(
|
||||
pixel_tick && h_count_reg === MaxHorizontal.U,
|
||||
Mux(v_count_reg === MaxVertical.U, 0.U, v_count_reg + 1.U),
|
||||
v_count_reg
|
||||
)
|
||||
|
||||
hsync_next := h_count_reg >= RetraceHorizontalStart.U && h_count_reg <= RetraceHorizontalEnd.U
|
||||
vsync_next := v_count_reg >= RetraceVerticalStart.U && v_count_reg <= RetraceVerticalEnd.U
|
||||
|
||||
pixel := pixel_next
|
||||
hsync_reg := hsync_next
|
||||
vsync_reg := vsync_next
|
||||
v_count_reg := v_count_next
|
||||
h_count_reg := h_count_next
|
||||
|
||||
io.video_on := h_count_reg < DisplayHorizontal.U && v_count_reg < DisplayVertical.U
|
||||
io.hsync := hsync_reg
|
||||
io.vsync := vsync_reg
|
||||
io.x := h_count_reg
|
||||
io.y := v_count_reg
|
||||
io.x_next := h_count_next
|
||||
io.y_next := v_count_next
|
||||
io.p_tick := pixel_tick
|
||||
io.f_tick := io.x === 0.U && io.y === 0.U
|
||||
}
|
||||
|
||||
class TMDS_encoder extends Module {
|
||||
val io = IO(new Bundle() {
|
||||
val video_data = Input(UInt(8.W)) //r,g,b,8bit
|
||||
val control_data = Input(UInt(2.W))
|
||||
val video_on = Input(Bool())
|
||||
val TMDS = Output(UInt(10.W))
|
||||
})
|
||||
val Nb1s = PopCount(io.video_data)
|
||||
val xored = xorfct(io.video_data)
|
||||
val xnored = xnorfct(io.video_data)
|
||||
val XNOR = (Nb1s > 4.U(4.W)) || (Nb1s === 4.U(4.W) && io.video_data(0) === 0.U)
|
||||
val q_m = RegInit(0.U(9.W))
|
||||
val diffSize = 4
|
||||
val diff = RegInit(0.S(diffSize.W))
|
||||
q_m := Mux(
|
||||
XNOR,
|
||||
xnored,
|
||||
xored
|
||||
)
|
||||
val disparitySize = 4
|
||||
val disparityReg = RegInit(0.S(disparitySize.W))
|
||||
diff := PopCount(q_m).asSInt - 4.S
|
||||
val doutReg = RegInit("b1010101011".U(10.W))
|
||||
|
||||
def xorfct(value: UInt): UInt = {
|
||||
val vin = VecInit(value.asBools)
|
||||
val res = VecInit(511.U.asBools)
|
||||
res(0) := vin(0)
|
||||
for (i <- 1 to 7) {
|
||||
res(i) := res(i - 1) ^ vin(i)
|
||||
}
|
||||
res(8) := 1.U
|
||||
res.asUInt
|
||||
}
|
||||
|
||||
def xnorfct(value: UInt): UInt = {
|
||||
val vin = VecInit(value.asBools)
|
||||
val res = VecInit(511.U.asBools)
|
||||
res(0) := vin(0)
|
||||
for (i <- 1 to 7) {
|
||||
res(i) := !(res(i - 1) ^ vin(i))
|
||||
}
|
||||
res(8) := 0.U
|
||||
res.asUInt
|
||||
}
|
||||
|
||||
when(io.video_on === false.B) {
|
||||
disparityReg := 0.S
|
||||
doutReg := "b1010101011".U(10.W)
|
||||
switch(io.control_data) {
|
||||
is("b00".U(2.W)) {
|
||||
doutReg := "b1101010100".U(10.W)
|
||||
}
|
||||
is("b01".U(2.W)) {
|
||||
doutReg := "b0010101011".U(10.W)
|
||||
}
|
||||
is("b10".U(2.W)) {
|
||||
doutReg := "b0101010100".U(10.W)
|
||||
}
|
||||
}
|
||||
}.otherwise {
|
||||
when(disparityReg === 0.S || diff === 0.S) {
|
||||
when(q_m(8) === false.B) {
|
||||
doutReg := "b10".U(2.W) ## ~q_m(7, 0)
|
||||
disparityReg := disparityReg - diff
|
||||
}.otherwise {
|
||||
doutReg := "b01".U(2.W) ## q_m(7, 0)
|
||||
disparityReg := disparityReg + diff
|
||||
}
|
||||
}.elsewhen((!diff(diffSize - 1) && !disparityReg(disparitySize - 1))
|
||||
|| (diff(diffSize - 1) && disparityReg(disparitySize - 1))) {
|
||||
doutReg := 1.U(1.W) ## q_m(8) ## ~q_m(7, 0)
|
||||
when(q_m(8)) {
|
||||
disparityReg := disparityReg + 1.S - diff
|
||||
}.otherwise {
|
||||
disparityReg := disparityReg - diff
|
||||
}
|
||||
}.otherwise {
|
||||
doutReg := 0.U(1.W) ## q_m
|
||||
when(q_m(8)) {
|
||||
disparityReg := disparityReg + diff
|
||||
}.otherwise {
|
||||
disparityReg := disparityReg - 1.S + diff
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
io.TMDS := doutReg
|
||||
}
|
||||
|
||||
class HDMIDisplay extends Module {
|
||||
val io = IO(new Bundle() {
|
||||
val rgb = Input(UInt(24.W))
|
||||
val x = Output(UInt(16.W))
|
||||
val y = Output(UInt(16.W))
|
||||
val x_next = Output(UInt(16.W))
|
||||
val y_next = Output(UInt(16.W))
|
||||
val video_on = Output(Bool())
|
||||
|
||||
val TMDSclk_p = Output(Bool())
|
||||
val TMDSdata_p = Output(UInt(3.W))
|
||||
val TMDSclk_n = Output(Bool())
|
||||
val TMDSdata_n = Output(UInt(3.W))
|
||||
})
|
||||
val rgb = io.rgb
|
||||
val pixel_clk = Wire(Bool())
|
||||
val hsync = Wire(Bool())
|
||||
val vsync = Wire(Bool())
|
||||
val sync = Module(new HDMISync)
|
||||
|
||||
io.x := sync.io.x
|
||||
io.y := sync.io.y
|
||||
io.x_next := sync.io.x_next
|
||||
io.y_next := sync.io.y_next
|
||||
io.video_on := sync.io.video_on
|
||||
|
||||
hsync := sync.io.hsync
|
||||
vsync := sync.io.vsync
|
||||
pixel_clk := sync.io.p_tick
|
||||
|
||||
// TMDS_PLLVR is a vivado IP core, check it in /verilog/pynq/TMDS_PLLVR.v
|
||||
val serial_clk = Wire(Clock())
|
||||
val pll_lock = Wire(Bool())
|
||||
val tmdspll = Module(new TMDS_PLLVR)
|
||||
val rst = Wire(Reset())
|
||||
tmdspll.io.clkin := pixel_clk.asClock
|
||||
serial_clk := tmdspll.io.clkout
|
||||
pll_lock := tmdspll.io.lock
|
||||
tmdspll.io.reset := reset
|
||||
rst := ~pll_lock
|
||||
|
||||
val tmds = Wire(UInt(3.W))
|
||||
val tmds_clk = Wire(Bool())
|
||||
withClockAndReset(pixel_clk.asClock, rst) {
|
||||
val tmds_channel1 = Wire(UInt(10.W))
|
||||
val tmds_channel2 = Wire(UInt(10.W))
|
||||
val tmds_channel0 = Wire(UInt(10.W))
|
||||
|
||||
val tmds_green = Module(new TMDS_encoder)
|
||||
val tmds_red = Module(new TMDS_encoder)
|
||||
val tmds_blue = Module(new TMDS_encoder)
|
||||
|
||||
tmds_red.io.video_on := sync.io.video_on
|
||||
tmds_blue.io.video_on := sync.io.video_on
|
||||
tmds_green.io.video_on := sync.io.video_on
|
||||
|
||||
tmds_blue.io.control_data := sync.io.vsync ## sync.io.hsync
|
||||
tmds_green.io.control_data := 0.U
|
||||
tmds_red.io.control_data := 0.U
|
||||
|
||||
tmds_red.io.video_data := rgb(23, 16)
|
||||
tmds_blue.io.video_data := rgb(7, 0)
|
||||
tmds_green.io.video_data := rgb(15, 8)
|
||||
|
||||
tmds_channel0 := tmds_blue.io.TMDS
|
||||
tmds_channel1 := tmds_green.io.TMDS
|
||||
tmds_channel2 := tmds_red.io.TMDS
|
||||
|
||||
val serdesBlue = Module(new Oser10Module())
|
||||
serdesBlue.io.data := tmds_channel0
|
||||
serdesBlue.io.fclk := serial_clk
|
||||
|
||||
val serdesGreen = Module(new Oser10Module())
|
||||
serdesGreen.io.data := tmds_channel1
|
||||
serdesGreen.io.fclk := serial_clk
|
||||
|
||||
val serdesRed = Module(new Oser10Module())
|
||||
serdesRed.io.data := tmds_channel2
|
||||
serdesRed.io.fclk := serial_clk
|
||||
|
||||
tmds := serdesRed.io.q ## serdesGreen.io.q ## serdesBlue.io.q
|
||||
|
||||
//serdesCLk : 25Mhz ,Why not directly use p_tick?
|
||||
//cause Duty Ratio of p_tick is 10% , while which of serdesCLk is 50%
|
||||
val serdesClk = Module(new Oser10Module())
|
||||
serdesClk.io.data := "b1111100000".U(10.W)
|
||||
serdesClk.io.fclk := serial_clk
|
||||
|
||||
tmds_clk := serdesClk.io.q
|
||||
|
||||
val buffDiffBlue = Module(new OBUFDS)
|
||||
buffDiffBlue.io.I := tmds(0)
|
||||
val buffDiffGreen = Module(new OBUFDS)
|
||||
buffDiffGreen.io.I := tmds(1)
|
||||
val buffDiffRed = Module(new OBUFDS)
|
||||
buffDiffRed.io.I := tmds(2)
|
||||
val buffDiffClk = Module(new OBUFDS)
|
||||
buffDiffClk.io.I := tmds_clk
|
||||
|
||||
io.TMDSclk_p := buffDiffClk.io.O
|
||||
io.TMDSclk_n := buffDiffClk.io.OB
|
||||
io.TMDSdata_p := buffDiffRed.io.O ## buffDiffGreen.io.O ## buffDiffBlue.io.O
|
||||
io.TMDSdata_n := buffDiffRed.io.OB ## buffDiffGreen.io.OB ## buffDiffBlue.io.OB
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
//PLL frequency multiplier using BlackBox
|
||||
class TMDS_PLLVR extends BlackBox {
|
||||
val io = IO(new Bundle {
|
||||
val clkin = Input(Clock())
|
||||
val reset = Input(Reset())
|
||||
val clkout = Output(Clock())
|
||||
val clkoutd = Output(Clock())
|
||||
val lock = Output(Bool())
|
||||
})
|
||||
}
|
||||
|
||||
/* OSER10 : serializer 10:1*/
|
||||
class OSER10 extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val Q = Output(Bool()) // OSER10 data output signal
|
||||
val D0 = Input(Bool())
|
||||
val D1 = Input(Bool())
|
||||
val D2 = Input(Bool())
|
||||
val D3 = Input(Bool())
|
||||
val D4 = Input(Bool())
|
||||
val D5 = Input(Bool())
|
||||
val D6 = Input(Bool())
|
||||
val D7 = Input(Bool())
|
||||
val D8 = Input(Bool())
|
||||
val D9 = Input(Bool()) // OSER10 data input signal
|
||||
val PCLK = Input(Clock()) // Primary clock input signal
|
||||
val FCLK = Input(Clock()) // High speed clock input signal
|
||||
val RESET = Input(Reset()) // Asynchronous reset input signal,
|
||||
//active-high.
|
||||
})
|
||||
withClockAndReset(io.FCLK, io.RESET) {
|
||||
val count = RegInit(0.U(4.W))
|
||||
val countnext = Wire(UInt(4.W))
|
||||
io.Q := MuxLookup(
|
||||
count,
|
||||
0.U,
|
||||
IndexedSeq(
|
||||
0.U -> io.D0.asBool,
|
||||
1.U -> io.D1.asBool,
|
||||
2.U -> io.D2.asBool,
|
||||
3.U -> io.D3.asBool,
|
||||
4.U -> io.D4.asBool,
|
||||
5.U -> io.D5.asBool,
|
||||
6.U -> io.D6.asBool,
|
||||
7.U -> io.D7.asBool,
|
||||
8.U -> io.D8.asBool,
|
||||
9.U -> io.D9.asBool
|
||||
)
|
||||
)
|
||||
countnext := Mux(
|
||||
count === 9.U, 0.U, count + 1.U
|
||||
)
|
||||
count := countnext
|
||||
}
|
||||
}
|
||||
|
||||
class Oser10Module extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val q = Output(Bool())
|
||||
val data = Input(UInt(10.W))
|
||||
val fclk = Input(Clock()) // Fast clock
|
||||
})
|
||||
|
||||
val osr10 = Module(new OSER10())
|
||||
io.q := osr10.io.Q
|
||||
osr10.io.D0 := io.data(0)
|
||||
osr10.io.D1 := io.data(1)
|
||||
osr10.io.D2 := io.data(2)
|
||||
osr10.io.D3 := io.data(3)
|
||||
osr10.io.D4 := io.data(4)
|
||||
osr10.io.D5 := io.data(5)
|
||||
osr10.io.D6 := io.data(6)
|
||||
osr10.io.D7 := io.data(7)
|
||||
osr10.io.D8 := io.data(8)
|
||||
osr10.io.D9 := io.data(9)
|
||||
osr10.io.PCLK := clock
|
||||
osr10.io.FCLK := io.fclk
|
||||
osr10.io.RESET := reset
|
||||
}
|
||||
|
||||
/* lvds output */
|
||||
class OBUFDS extends BlackBox {
|
||||
val io = IO(new Bundle {
|
||||
val O = Output(Bool())
|
||||
val OB = Output(Bool())
|
||||
val I = Input(Bool())
|
||||
})
|
||||
}
|
||||
//-----------------------------------------
|
||||
|
||||
|
||||
//-----------------------------------------
|
||||
|
||||
|
||||
68
lab1/src/main/scala/peripheral/InstructionROM.scala
Normal file
68
lab1/src/main/scala/peripheral/InstructionROM.scala
Normal file
@@ -0,0 +1,68 @@
|
||||
// Copyright 2021 Howard Lau
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package peripheral
|
||||
|
||||
import chisel3._
|
||||
import chisel3.experimental.{ChiselAnnotation, annotate}
|
||||
import chisel3.util.experimental.loadMemoryFromFileInline
|
||||
import firrtl.annotations.MemorySynthInit
|
||||
import riscv.Parameters
|
||||
|
||||
import java.io.FileWriter
|
||||
import java.nio.file.{Files, Paths}
|
||||
import java.nio.{ByteBuffer, ByteOrder}
|
||||
|
||||
class InstructionROM(instructionFilename: String) extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val address = Input(UInt(Parameters.AddrWidth))
|
||||
val data = Output(UInt(Parameters.InstructionWidth))
|
||||
})
|
||||
|
||||
val (instructionsInitFile, capacity) = readAsmBinary(instructionFilename)
|
||||
val mem = Mem(capacity, UInt(Parameters.InstructionWidth))
|
||||
annotate(new ChiselAnnotation {
|
||||
override def toFirrtl =
|
||||
MemorySynthInit
|
||||
})
|
||||
loadMemoryFromFileInline(mem, instructionsInitFile.toString.replaceAll("\\\\", "/"))
|
||||
io.data := mem.read(io.address)
|
||||
|
||||
def readAsmBinary(filename: String) = {
|
||||
val inputStream = if (Files.exists(Paths.get(filename))) {
|
||||
Files.newInputStream(Paths.get(filename))
|
||||
} else {
|
||||
getClass.getClassLoader.getResourceAsStream(filename)
|
||||
}
|
||||
var instructions = new Array[BigInt](0)
|
||||
val arr = new Array[Byte](4)
|
||||
while (inputStream.read(arr) == 4) {
|
||||
val instBuf = ByteBuffer.wrap(arr)
|
||||
instBuf.order(ByteOrder.LITTLE_ENDIAN)
|
||||
val inst = BigInt(instBuf.getInt() & 0xFFFFFFFFL)
|
||||
instructions = instructions :+ inst
|
||||
}
|
||||
instructions = instructions :+ BigInt(0x00000013L)
|
||||
instructions = instructions :+ BigInt(0x00000013L)
|
||||
instructions = instructions :+ BigInt(0x00000013L)
|
||||
val currentDir = System.getProperty("user.dir")
|
||||
val exeTxtPath = Paths.get(currentDir, "verilog", f"${instructionFilename}.txt")
|
||||
val writer = new FileWriter(exeTxtPath.toString)
|
||||
for (i <- instructions.indices) {
|
||||
writer.write(f"@$i%x\n${instructions(i)}%08x\n")
|
||||
}
|
||||
writer.close()
|
||||
(exeTxtPath, instructions.length)
|
||||
}
|
||||
}
|
||||
77
lab1/src/main/scala/peripheral/Memory.scala
Normal file
77
lab1/src/main/scala/peripheral/Memory.scala
Normal file
@@ -0,0 +1,77 @@
|
||||
// Copyright 2021 Howard Lau
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package peripheral
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
import riscv.Parameters
|
||||
|
||||
class RAMBundle extends Bundle {
|
||||
val address = Input(UInt(Parameters.AddrWidth))
|
||||
val write_data = Input(UInt(Parameters.DataWidth))
|
||||
val write_enable = Input(Bool())
|
||||
val write_strobe = Input(Vec(Parameters.WordSize, Bool()))
|
||||
val read_data = Output(UInt(Parameters.DataWidth))
|
||||
}
|
||||
// The purpose of this module is to help the synthesis tool recognize
|
||||
// our memory as a Block RAM template
|
||||
class BlockRAM(capacity: Int) extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val read_address = Input(UInt(Parameters.AddrWidth))
|
||||
val write_address = Input(UInt(Parameters.AddrWidth))
|
||||
val write_data = Input(UInt(Parameters.DataWidth))
|
||||
val write_enable = Input(Bool())
|
||||
val write_strobe = Input(Vec(Parameters.WordSize, Bool()))
|
||||
|
||||
val debug_read_address = Input(UInt(Parameters.AddrWidth))
|
||||
|
||||
val read_data = Output(UInt(Parameters.DataWidth))
|
||||
val debug_read_data = Output(UInt(Parameters.DataWidth))
|
||||
})
|
||||
val mem = SyncReadMem(capacity, Vec(Parameters.WordSize, UInt(Parameters.ByteWidth)))
|
||||
when(io.write_enable) {
|
||||
val write_data_vec = Wire(Vec(Parameters.WordSize, UInt(Parameters.ByteWidth)))
|
||||
for (i <- 0 until Parameters.WordSize) {
|
||||
write_data_vec(i) := io.write_data((i + 1) * Parameters.ByteBits - 1, i * Parameters.ByteBits)
|
||||
}
|
||||
mem.write((io.write_address >> 2.U).asUInt, write_data_vec, io.write_strobe)
|
||||
}
|
||||
io.read_data := mem.read((io.read_address >> 2.U).asUInt, true.B).asUInt
|
||||
io.debug_read_data := mem.read((io.debug_read_address >> 2.U).asUInt, true.B).asUInt
|
||||
}
|
||||
|
||||
class Memory(capacity: Int) extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val bundle = new RAMBundle
|
||||
|
||||
val instruction = Output(UInt(Parameters.DataWidth))
|
||||
val instruction_address = Input(UInt(Parameters.AddrWidth))
|
||||
|
||||
val debug_read_address = Input(UInt(Parameters.AddrWidth))
|
||||
val debug_read_data = Output(UInt(Parameters.DataWidth))
|
||||
})
|
||||
|
||||
val mem = SyncReadMem(capacity, Vec(Parameters.WordSize, UInt(Parameters.ByteWidth)))
|
||||
when(io.bundle.write_enable) {
|
||||
val write_data_vec = Wire(Vec(Parameters.WordSize, UInt(Parameters.ByteWidth)))
|
||||
for (i <- 0 until Parameters.WordSize) {
|
||||
write_data_vec(i) := io.bundle.write_data((i + 1) * Parameters.ByteBits - 1, i * Parameters.ByteBits)
|
||||
}
|
||||
mem.write((io.bundle.address >> 2.U).asUInt, write_data_vec, io.bundle.write_strobe)
|
||||
}
|
||||
io.bundle.read_data := mem.read((io.bundle.address >> 2.U).asUInt, true.B).asUInt
|
||||
io.debug_read_data := mem.read((io.debug_read_address >> 2.U).asUInt, true.B).asUInt
|
||||
io.instruction := mem.read((io.instruction_address >> 2.U).asUInt, true.B).asUInt
|
||||
}
|
||||
50
lab1/src/main/scala/peripheral/ROMLoader.scala
Normal file
50
lab1/src/main/scala/peripheral/ROMLoader.scala
Normal file
@@ -0,0 +1,50 @@
|
||||
// Copyright 2021 Howard Lau
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package peripheral
|
||||
|
||||
import chisel3._
|
||||
import riscv.Parameters
|
||||
|
||||
class ROMLoader(capacity: Int) extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val bundle = Flipped(new RAMBundle)
|
||||
|
||||
val rom_address = Output(UInt(Parameters.AddrWidth))
|
||||
val rom_data = Input(UInt(Parameters.InstructionWidth))
|
||||
|
||||
val load_address = Input(UInt(Parameters.AddrWidth))
|
||||
val load_finished = Output(Bool())
|
||||
})
|
||||
|
||||
val address = RegInit(0.U(32.W))
|
||||
val valid = RegInit(false.B)
|
||||
|
||||
io.bundle.write_strobe := VecInit(Seq.fill(Parameters.WordSize)(false.B))
|
||||
io.bundle.address := 0.U
|
||||
io.bundle.write_data := 0.U
|
||||
io.bundle.write_enable := false.B
|
||||
when(address <= (capacity - 1).U) {
|
||||
io.bundle.write_enable := true.B
|
||||
io.bundle.write_data := io.rom_data
|
||||
io.bundle.address := (address << 2.U).asUInt + io.load_address
|
||||
io.bundle.write_strobe := VecInit(Seq.fill(Parameters.WordSize)(true.B))
|
||||
address := address + 1.U
|
||||
when(address === (capacity - 1).U) {
|
||||
valid := true.B
|
||||
}
|
||||
}
|
||||
io.load_finished := valid
|
||||
io.rom_address := address
|
||||
}
|
||||
116
lab1/src/main/scala/peripheral/VGADisplay.scala
Normal file
116
lab1/src/main/scala/peripheral/VGADisplay.scala
Normal file
@@ -0,0 +1,116 @@
|
||||
// Copyright 2021 Howard Lau
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package peripheral
|
||||
|
||||
import chisel3._
|
||||
|
||||
|
||||
class VGASync extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val hsync = Output(Bool())
|
||||
val vsync = Output(Bool())
|
||||
val video_on = Output(Bool())
|
||||
val p_tick = Output(Bool())
|
||||
val f_tick = Output(Bool())
|
||||
val x = Output(UInt(10.W))
|
||||
val y = Output(UInt(10.W))
|
||||
})
|
||||
|
||||
val DisplayHorizontal = ScreenInfo.DisplayHorizontal
|
||||
val DisplayVertical = ScreenInfo.DisplayVertical
|
||||
|
||||
val BorderLeft = 48
|
||||
val BorderRight = 16
|
||||
val BorderTop = 10
|
||||
val BorderBottom = 33
|
||||
|
||||
val RetraceHorizontal = 96
|
||||
val RetraceVertical = 2
|
||||
|
||||
val MaxHorizontal = DisplayHorizontal + BorderLeft + BorderRight + RetraceHorizontal - 1
|
||||
val MaxVertical = DisplayVertical + BorderTop + BorderBottom + RetraceVertical - 1
|
||||
|
||||
val RetraceHorizontalStart = DisplayHorizontal + BorderRight
|
||||
val RetraceHorizontalEnd = RetraceHorizontalStart + RetraceHorizontal - 1
|
||||
|
||||
val RetraceVerticalStart = DisplayVertical + BorderBottom
|
||||
val RetraceVerticalEnd = RetraceVerticalStart + RetraceVertical - 1
|
||||
|
||||
val pixel = RegInit(UInt(2.W), 0.U)
|
||||
val pixel_next = Wire(UInt(2.W))
|
||||
val pixel_tick = Wire(Bool())
|
||||
|
||||
val v_count_reg = RegInit(UInt(10.W), 0.U)
|
||||
val h_count_reg = RegInit(UInt(10.W), 0.U)
|
||||
|
||||
val v_count_next = Wire(UInt(10.W))
|
||||
val h_count_next = Wire(UInt(10.W))
|
||||
|
||||
val vsync_reg = RegInit(Bool(), false.B)
|
||||
val hsync_reg = RegInit(Bool(), false.B)
|
||||
|
||||
val vsync_next = Wire(Bool())
|
||||
val hsync_next = Wire(Bool())
|
||||
|
||||
pixel_next := pixel + 1.U
|
||||
pixel_tick := pixel === 0.U
|
||||
|
||||
h_count_next := Mux(
|
||||
pixel_tick,
|
||||
Mux(h_count_reg === MaxHorizontal.U, 0.U, h_count_reg + 1.U),
|
||||
h_count_reg
|
||||
)
|
||||
|
||||
v_count_next := Mux(
|
||||
pixel_tick && h_count_reg === MaxHorizontal.U,
|
||||
Mux(v_count_reg === MaxVertical.U, 0.U, v_count_reg + 1.U),
|
||||
v_count_reg
|
||||
)
|
||||
|
||||
hsync_next := h_count_reg >= RetraceHorizontalStart.U && h_count_reg <= RetraceHorizontalEnd.U
|
||||
vsync_next := v_count_reg >= RetraceVerticalStart.U && v_count_reg <= RetraceVerticalEnd.U
|
||||
|
||||
pixel := pixel_next
|
||||
hsync_reg := hsync_next
|
||||
vsync_reg := vsync_next
|
||||
v_count_reg := v_count_next
|
||||
h_count_reg := h_count_next
|
||||
|
||||
io.video_on := h_count_reg < DisplayHorizontal.U && v_count_reg < DisplayVertical.U
|
||||
io.hsync := hsync_reg
|
||||
io.vsync := vsync_reg
|
||||
io.x := h_count_reg
|
||||
io.y := v_count_reg
|
||||
io.p_tick := pixel_tick
|
||||
io.f_tick := io.x === 0.U && io.y === 0.U
|
||||
}
|
||||
|
||||
class VGADisplay extends Module {
|
||||
val io = IO(new Bundle() {
|
||||
val x = Output(UInt(16.W))
|
||||
val y = Output(UInt(16.W))
|
||||
val video_on = Output(Bool())
|
||||
|
||||
val hsync = Output(Bool())
|
||||
val vsync = Output(Bool())
|
||||
})
|
||||
|
||||
val sync = Module(new VGASync)
|
||||
io.hsync := sync.io.hsync
|
||||
io.vsync := sync.io.vsync
|
||||
io.x := sync.io.x
|
||||
io.y := sync.io.y
|
||||
io.video_on := sync.io.y
|
||||
}
|
||||
28
lab1/src/main/scala/riscv/CPUBundle.scala
Normal file
28
lab1/src/main/scala/riscv/CPUBundle.scala
Normal file
@@ -0,0 +1,28 @@
|
||||
// Copyright 2022 Howard Lau
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package riscv
|
||||
|
||||
import chisel3._
|
||||
import peripheral.RAMBundle
|
||||
|
||||
class CPUBundle extends Bundle {
|
||||
val instruction_address = Output(UInt(Parameters.AddrWidth))
|
||||
val instruction = Input(UInt(Parameters.DataWidth))
|
||||
val memory_bundle = Flipped(new RAMBundle)
|
||||
val instruction_valid = Input(Bool())
|
||||
val deviceSelect = Output(UInt(Parameters.SlaveDeviceCountBits.W))
|
||||
val debug_read_address = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val debug_read_data = Output(UInt(Parameters.DataWidth))
|
||||
}
|
||||
58
lab1/src/main/scala/riscv/Parameters.scala
Normal file
58
lab1/src/main/scala/riscv/Parameters.scala
Normal file
@@ -0,0 +1,58 @@
|
||||
// Copyright 2021 Howard Lau
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package riscv
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
|
||||
object ImplementationType {
|
||||
val ThreeStage = 0
|
||||
val FiveStage = 1
|
||||
}
|
||||
|
||||
object Parameters {
|
||||
val AddrBits = 32
|
||||
val AddrWidth = AddrBits.W
|
||||
|
||||
val InstructionBits = 32
|
||||
val InstructionWidth = InstructionBits.W
|
||||
val DataBits = 32
|
||||
val DataWidth = DataBits.W
|
||||
val ByteBits = 8
|
||||
val ByteWidth = ByteBits.W
|
||||
val WordSize = Math.ceil(DataBits / ByteBits).toInt
|
||||
|
||||
val PhysicalRegisters = 32
|
||||
val PhysicalRegisterAddrBits = log2Up(PhysicalRegisters)
|
||||
val PhysicalRegisterAddrWidth = PhysicalRegisterAddrBits.W
|
||||
|
||||
val CSRRegisterAddrBits = 12
|
||||
val CSRRegisterAddrWidth = CSRRegisterAddrBits.W
|
||||
|
||||
val InterruptFlagBits = 32
|
||||
val InterruptFlagWidth = InterruptFlagBits.W
|
||||
|
||||
val HoldStateBits = 3
|
||||
val StallStateWidth = HoldStateBits.W
|
||||
|
||||
val MemorySizeInBytes = 32768
|
||||
val MemorySizeInWords = MemorySizeInBytes / 4
|
||||
|
||||
val EntryAddress = 0x1000.U(Parameters.AddrWidth)
|
||||
|
||||
val MasterDeviceCount = 1
|
||||
val SlaveDeviceCount = 8
|
||||
val SlaveDeviceCountBits = log2Up(Parameters.SlaveDeviceCount)
|
||||
}
|
||||
70
lab1/src/main/scala/riscv/core/ALU.scala
Normal file
70
lab1/src/main/scala/riscv/core/ALU.scala
Normal file
@@ -0,0 +1,70 @@
|
||||
// Copyright 2021 Howard Lau
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package riscv.core
|
||||
|
||||
import chisel3._
|
||||
import chisel3.experimental.ChiselEnum
|
||||
import chisel3.util._
|
||||
import riscv.Parameters
|
||||
|
||||
object ALUFunctions extends ChiselEnum {
|
||||
val zero, add, sub, sll, slt, xor, or, and, srl, sra, sltu = Value
|
||||
}
|
||||
|
||||
class ALU extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val func = Input(ALUFunctions())
|
||||
|
||||
val op1 = Input(UInt(Parameters.DataWidth))
|
||||
val op2 = Input(UInt(Parameters.DataWidth))
|
||||
|
||||
val result = Output(UInt(Parameters.DataWidth))
|
||||
})
|
||||
|
||||
io.result := 0.U
|
||||
switch(io.func) {
|
||||
is(ALUFunctions.add) {
|
||||
io.result := io.op1 + io.op2
|
||||
}
|
||||
is(ALUFunctions.sub) {
|
||||
io.result := io.op1 - io.op2
|
||||
}
|
||||
is(ALUFunctions.sll) {
|
||||
io.result := io.op1 << io.op2(4, 0)
|
||||
}
|
||||
is(ALUFunctions.slt) {
|
||||
io.result := io.op1.asSInt < io.op2.asSInt
|
||||
}
|
||||
is(ALUFunctions.xor) {
|
||||
io.result := io.op1 ^ io.op2
|
||||
}
|
||||
is(ALUFunctions.or) {
|
||||
io.result := io.op1 | io.op2
|
||||
}
|
||||
is(ALUFunctions.and) {
|
||||
io.result := io.op1 & io.op2
|
||||
}
|
||||
is(ALUFunctions.srl) {
|
||||
io.result := io.op1 >> io.op2(4, 0)
|
||||
}
|
||||
is(ALUFunctions.sra) {
|
||||
io.result := (io.op1.asSInt >> io.op2(4, 0)).asUInt
|
||||
}
|
||||
is(ALUFunctions.sltu) {
|
||||
io.result := io.op1 < io.op2
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
86
lab1/src/main/scala/riscv/core/ALUControl.scala
Normal file
86
lab1/src/main/scala/riscv/core/ALUControl.scala
Normal file
@@ -0,0 +1,86 @@
|
||||
// Copyright 2021 Howard Lau
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package riscv.core
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
|
||||
class ALUControl extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val opcode = Input(UInt(7.W))
|
||||
val funct3 = Input(UInt(3.W))
|
||||
val funct7 = Input(UInt(7.W))
|
||||
|
||||
val alu_funct = Output(ALUFunctions())
|
||||
})
|
||||
|
||||
io.alu_funct := ALUFunctions.zero
|
||||
|
||||
switch(io.opcode) {
|
||||
is(InstructionTypes.I) {
|
||||
io.alu_funct := MuxLookup(
|
||||
io.funct3,
|
||||
ALUFunctions.zero,
|
||||
IndexedSeq(
|
||||
InstructionsTypeI.addi -> ALUFunctions.add,
|
||||
InstructionsTypeI.slli -> ALUFunctions.sll,
|
||||
InstructionsTypeI.slti -> ALUFunctions.slt,
|
||||
InstructionsTypeI.sltiu -> ALUFunctions.sltu,
|
||||
InstructionsTypeI.xori -> ALUFunctions.xor,
|
||||
InstructionsTypeI.ori -> ALUFunctions.or,
|
||||
InstructionsTypeI.andi -> ALUFunctions.and,
|
||||
InstructionsTypeI.sri -> Mux(io.funct7(5), ALUFunctions.sra, ALUFunctions.srl)
|
||||
),
|
||||
)
|
||||
}
|
||||
is(InstructionTypes.RM) {
|
||||
io.alu_funct := MuxLookup(
|
||||
io.funct3,
|
||||
ALUFunctions.zero,
|
||||
IndexedSeq(
|
||||
InstructionsTypeR.add_sub -> Mux(io.funct7(5), ALUFunctions.sub, ALUFunctions.add),
|
||||
InstructionsTypeR.sll -> ALUFunctions.sll,
|
||||
InstructionsTypeR.slt -> ALUFunctions.slt,
|
||||
InstructionsTypeR.sltu -> ALUFunctions.sltu,
|
||||
InstructionsTypeR.xor -> ALUFunctions.xor,
|
||||
InstructionsTypeR.or -> ALUFunctions.or,
|
||||
InstructionsTypeR.and -> ALUFunctions.and,
|
||||
InstructionsTypeR.sr -> Mux(io.funct7(5), ALUFunctions.sra, ALUFunctions.srl)
|
||||
),
|
||||
)
|
||||
}
|
||||
is(InstructionTypes.B) {
|
||||
io.alu_funct := ALUFunctions.add
|
||||
}
|
||||
is(InstructionTypes.L) {
|
||||
io.alu_funct := ALUFunctions.add
|
||||
}
|
||||
is(InstructionTypes.S) {
|
||||
io.alu_funct := ALUFunctions.add
|
||||
}
|
||||
is(Instructions.jal) {
|
||||
io.alu_funct := ALUFunctions.add
|
||||
}
|
||||
is(Instructions.jalr) {
|
||||
io.alu_funct := ALUFunctions.add
|
||||
}
|
||||
is(Instructions.lui) {
|
||||
io.alu_funct := ALUFunctions.add
|
||||
}
|
||||
is(Instructions.auipc) {
|
||||
io.alu_funct := ALUFunctions.add
|
||||
}
|
||||
}
|
||||
}
|
||||
77
lab1/src/main/scala/riscv/core/CPU.scala
Normal file
77
lab1/src/main/scala/riscv/core/CPU.scala
Normal file
@@ -0,0 +1,77 @@
|
||||
// Copyright 2021 Howard Lau
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package riscv.core
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util.Cat
|
||||
import riscv.{CPUBundle, Parameters}
|
||||
|
||||
class CPU extends Module {
|
||||
val io = IO(new CPUBundle)
|
||||
|
||||
val regs = Module(new RegisterFile)
|
||||
val inst_fetch = Module(new InstructionFetch)
|
||||
val id = Module(new InstructionDecode)
|
||||
val ex = Module(new Execute)
|
||||
val mem = Module(new MemoryAccess)
|
||||
val wb = Module(new WriteBack)
|
||||
|
||||
|
||||
io.deviceSelect := mem.io.memory_bundle.address(Parameters.AddrBits - 1, Parameters.AddrBits - Parameters.SlaveDeviceCountBits)
|
||||
|
||||
inst_fetch.io.jump_address_id := ex.io.if_jump_address
|
||||
inst_fetch.io.jump_flag_id := ex.io.if_jump_flag
|
||||
inst_fetch.io.instruction_valid := io.instruction_valid
|
||||
inst_fetch.io.instruction_read_data := io.instruction
|
||||
io.instruction_address := inst_fetch.io.instruction_address
|
||||
|
||||
regs.io.write_enable := id.io.reg_write_enable
|
||||
regs.io.write_address := id.io.reg_write_address
|
||||
regs.io.write_data := wb.io.regs_write_data
|
||||
regs.io.read_address1 := id.io.regs_reg1_read_address
|
||||
regs.io.read_address2 := id.io.regs_reg2_read_address
|
||||
|
||||
regs.io.debug_read_address := io.debug_read_address
|
||||
io.debug_read_data := regs.io.debug_read_data
|
||||
|
||||
id.io.instruction := inst_fetch.io.instruction
|
||||
|
||||
// lab1(cpu)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// lab1(cpu) end
|
||||
|
||||
|
||||
mem.io.alu_result := ex.io.mem_alu_result
|
||||
mem.io.reg2_data := regs.io.read_data2
|
||||
mem.io.memory_read_enable := id.io.memory_read_enable
|
||||
mem.io.memory_write_enable := id.io.memory_write_enable
|
||||
mem.io.funct3 := inst_fetch.io.instruction(14, 12)
|
||||
|
||||
io.memory_bundle.address := Cat(0.U(Parameters.SlaveDeviceCountBits.W),mem.io.memory_bundle.address(Parameters.AddrBits - 1 - Parameters.SlaveDeviceCountBits, 0))
|
||||
io.memory_bundle.write_enable := mem.io.memory_bundle.write_enable
|
||||
io.memory_bundle.write_data := mem.io.memory_bundle.write_data
|
||||
io.memory_bundle.write_strobe := mem.io.memory_bundle.write_strobe
|
||||
mem.io.memory_bundle.read_data := io.memory_bundle.read_data
|
||||
|
||||
wb.io.instruction_address := inst_fetch.io.instruction_address
|
||||
wb.io.alu_result := ex.io.mem_alu_result
|
||||
wb.io.memory_read_data := mem.io.wb_memory_read_data
|
||||
wb.io.regs_write_source := id.io.wb_reg_write_source
|
||||
}
|
||||
75
lab1/src/main/scala/riscv/core/Execute.scala
Normal file
75
lab1/src/main/scala/riscv/core/Execute.scala
Normal file
@@ -0,0 +1,75 @@
|
||||
// Copyright 2021 Howard Lau
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package riscv.core
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util.{Cat, MuxLookup}
|
||||
import riscv.Parameters
|
||||
|
||||
class Execute extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val instruction = Input(UInt(Parameters.InstructionWidth))
|
||||
val instruction_address = Input(UInt(Parameters.AddrWidth))
|
||||
val reg1_data = Input(UInt(Parameters.DataWidth))
|
||||
val reg2_data = Input(UInt(Parameters.DataWidth))
|
||||
val immediate = Input(UInt(Parameters.DataWidth))
|
||||
val aluop1_source = Input(UInt(1.W))
|
||||
val aluop2_source = Input(UInt(1.W))
|
||||
|
||||
val mem_alu_result = Output(UInt(Parameters.DataWidth))
|
||||
val if_jump_flag = Output(Bool())
|
||||
val if_jump_address = Output(UInt(Parameters.DataWidth))
|
||||
})
|
||||
|
||||
val opcode = io.instruction(6, 0)
|
||||
val funct3 = io.instruction(14, 12)
|
||||
val funct7 = io.instruction(31, 25)
|
||||
val rd = io.instruction(11, 7)
|
||||
val uimm = io.instruction(19, 15)
|
||||
|
||||
val alu = Module(new ALU)
|
||||
val alu_ctrl = Module(new ALUControl)
|
||||
|
||||
alu_ctrl.io.opcode := opcode
|
||||
alu_ctrl.io.funct3 := funct3
|
||||
alu_ctrl.io.funct7 := funct7
|
||||
|
||||
// lab1(Execute)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// lab1(Execute) end
|
||||
|
||||
io.mem_alu_result := alu.io.result
|
||||
io.if_jump_flag := opcode === Instructions.jal ||
|
||||
(opcode === Instructions.jalr) ||
|
||||
(opcode === InstructionTypes.B) && MuxLookup(
|
||||
funct3,
|
||||
false.B,
|
||||
IndexedSeq(
|
||||
InstructionsTypeB.beq -> (io.reg1_data === io.reg2_data),
|
||||
InstructionsTypeB.bne -> (io.reg1_data =/= io.reg2_data),
|
||||
InstructionsTypeB.blt -> (io.reg1_data.asSInt < io.reg2_data.asSInt),
|
||||
InstructionsTypeB.bge -> (io.reg1_data.asSInt >= io.reg2_data.asSInt),
|
||||
InstructionsTypeB.bltu -> (io.reg1_data.asUInt < io.reg2_data.asUInt),
|
||||
InstructionsTypeB.bgeu -> (io.reg1_data.asUInt >= io.reg2_data.asUInt)
|
||||
)
|
||||
)
|
||||
io.if_jump_address := io.immediate + Mux(opcode === Instructions.jalr, io.reg1_data, io.instruction_address)
|
||||
}
|
||||
193
lab1/src/main/scala/riscv/core/InstructionDecode.scala
Normal file
193
lab1/src/main/scala/riscv/core/InstructionDecode.scala
Normal file
@@ -0,0 +1,193 @@
|
||||
// Copyright 2021 Howard Lau
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package riscv.core
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
import riscv.Parameters
|
||||
|
||||
object InstructionTypes {
|
||||
val L = "b0000011".U
|
||||
val I = "b0010011".U
|
||||
val S = "b0100011".U
|
||||
val RM = "b0110011".U
|
||||
val B = "b1100011".U
|
||||
}
|
||||
|
||||
object Instructions {
|
||||
val lui = "b0110111".U
|
||||
val nop = "b0000001".U
|
||||
val jal = "b1101111".U
|
||||
val jalr = "b1100111".U
|
||||
val auipc = "b0010111".U
|
||||
val csr = "b1110011".U
|
||||
val fence = "b0001111".U
|
||||
}
|
||||
|
||||
object InstructionsTypeL {
|
||||
val lb = "b000".U
|
||||
val lh = "b001".U
|
||||
val lw = "b010".U
|
||||
val lbu = "b100".U
|
||||
val lhu = "b101".U
|
||||
}
|
||||
|
||||
object InstructionsTypeI {
|
||||
val addi = 0.U
|
||||
val slli = 1.U
|
||||
val slti = 2.U
|
||||
val sltiu = 3.U
|
||||
val xori = 4.U
|
||||
val sri = 5.U
|
||||
val ori = 6.U
|
||||
val andi = 7.U
|
||||
}
|
||||
|
||||
object InstructionsTypeS {
|
||||
val sb = "b000".U
|
||||
val sh = "b001".U
|
||||
val sw = "b010".U
|
||||
}
|
||||
|
||||
object InstructionsTypeR {
|
||||
val add_sub = 0.U
|
||||
val sll = 1.U
|
||||
val slt = 2.U
|
||||
val sltu = 3.U
|
||||
val xor = 4.U
|
||||
val sr = 5.U
|
||||
val or = 6.U
|
||||
val and = 7.U
|
||||
}
|
||||
|
||||
object InstructionsTypeM {
|
||||
val mul = 0.U
|
||||
val mulh = 1.U
|
||||
val mulhsu = 2.U
|
||||
val mulhum = 3.U
|
||||
val div = 4.U
|
||||
val divu = 5.U
|
||||
val rem = 6.U
|
||||
val remu = 7.U
|
||||
}
|
||||
|
||||
object InstructionsTypeB {
|
||||
val beq = "b000".U
|
||||
val bne = "b001".U
|
||||
val blt = "b100".U
|
||||
val bge = "b101".U
|
||||
val bltu = "b110".U
|
||||
val bgeu = "b111".U
|
||||
}
|
||||
|
||||
object InstructionsTypeCSR {
|
||||
val csrrw = "b001".U
|
||||
val csrrs = "b010".U
|
||||
val csrrc = "b011".U
|
||||
val csrrwi = "b101".U
|
||||
val csrrsi = "b110".U
|
||||
val csrrci = "b111".U
|
||||
}
|
||||
|
||||
object InstructionsNop {
|
||||
val nop = 0x00000013L.U(Parameters.DataWidth)
|
||||
}
|
||||
|
||||
object InstructionsRet {
|
||||
val mret = 0x30200073L.U(Parameters.DataWidth)
|
||||
val ret = 0x00008067L.U(Parameters.DataWidth)
|
||||
}
|
||||
|
||||
object InstructionsEnv {
|
||||
val ecall = 0x00000073L.U(Parameters.DataWidth)
|
||||
val ebreak = 0x00100073L.U(Parameters.DataWidth)
|
||||
}
|
||||
|
||||
object ALUOp1Source {
|
||||
val Register = 0.U(1.W)
|
||||
val InstructionAddress = 1.U(1.W)
|
||||
}
|
||||
|
||||
object ALUOp2Source {
|
||||
val Register = 0.U(1.W)
|
||||
val Immediate = 1.U(1.W)
|
||||
}
|
||||
|
||||
object RegWriteSource {
|
||||
val ALUResult = 0.U(2.W)
|
||||
val Memory = 1.U(2.W)
|
||||
//val CSR = 2.U(2.W)
|
||||
val NextInstructionAddress = 3.U(2.W)
|
||||
}
|
||||
|
||||
class InstructionDecode extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val instruction = Input(UInt(Parameters.InstructionWidth))
|
||||
|
||||
val regs_reg1_read_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val regs_reg2_read_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val ex_immediate = Output(UInt(Parameters.DataWidth))
|
||||
val ex_aluop1_source = Output(UInt(1.W))
|
||||
val ex_aluop2_source = Output(UInt(1.W))
|
||||
val memory_read_enable = Output(Bool())
|
||||
val memory_write_enable = Output(Bool())
|
||||
val wb_reg_write_source = Output(UInt(2.W))
|
||||
val reg_write_enable = Output(Bool())
|
||||
val reg_write_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
})
|
||||
val opcode = io.instruction(6, 0)
|
||||
val funct3 = io.instruction(14, 12)
|
||||
val funct7 = io.instruction(31, 25)
|
||||
val rd = io.instruction(11, 7)
|
||||
val rs1 = io.instruction(19, 15)
|
||||
val rs2 = io.instruction(24, 20)
|
||||
|
||||
io.regs_reg1_read_address := Mux(opcode === Instructions.lui, 0.U(Parameters.PhysicalRegisterAddrWidth), rs1)
|
||||
io.regs_reg2_read_address := rs2
|
||||
val immediate = MuxLookup(
|
||||
opcode,
|
||||
Cat(Fill(20, io.instruction(31)), io.instruction(31, 20)),
|
||||
IndexedSeq(
|
||||
InstructionTypes.I -> Cat(Fill(21, io.instruction(31)), io.instruction(30, 20)),
|
||||
InstructionTypes.L -> Cat(Fill(21, io.instruction(31)), io.instruction(30, 20)),
|
||||
Instructions.jalr -> Cat(Fill(21, io.instruction(31)), io.instruction(30, 20)),
|
||||
InstructionTypes.S -> Cat(Fill(21, io.instruction(31)), io.instruction(30, 25), io.instruction(11, 7)),
|
||||
InstructionTypes.B -> Cat(Fill(20, io.instruction(31)), io.instruction(7), io.instruction(30, 25), io.instruction(11, 8), 0.U(1.W)),
|
||||
Instructions.lui -> Cat(io.instruction(31, 12), 0.U(12.W)),
|
||||
Instructions.auipc -> Cat(io.instruction(31, 12), 0.U(12.W)),
|
||||
Instructions.jal -> Cat(Fill(12, io.instruction(31)), io.instruction(19, 12), io.instruction(20), io.instruction(30, 21), 0.U(1.W))
|
||||
)
|
||||
)
|
||||
io.ex_immediate := immediate
|
||||
io.ex_aluop1_source := Mux(
|
||||
opcode === Instructions.auipc || opcode === InstructionTypes.B || opcode === Instructions.jal,
|
||||
ALUOp1Source.InstructionAddress,
|
||||
ALUOp1Source.Register
|
||||
)
|
||||
|
||||
// lab1(InstructionDecode)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// lab1(InstructionDecode) end
|
||||
io.reg_write_enable := (opcode === InstructionTypes.RM) || (opcode === InstructionTypes.I) ||
|
||||
(opcode === InstructionTypes.L) || (opcode === Instructions.auipc) || (opcode === Instructions.lui) ||
|
||||
(opcode === Instructions.jal) || (opcode === Instructions.jalr)
|
||||
io.reg_write_address := io.instruction(11, 7)
|
||||
}
|
||||
50
lab1/src/main/scala/riscv/core/InstructionFetch.scala
Normal file
50
lab1/src/main/scala/riscv/core/InstructionFetch.scala
Normal file
@@ -0,0 +1,50 @@
|
||||
// Copyright 2021 Howard Lau
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package riscv.core
|
||||
|
||||
import chisel3._
|
||||
import riscv.Parameters
|
||||
|
||||
object ProgramCounter {
|
||||
val EntryAddress = Parameters.EntryAddress
|
||||
}
|
||||
|
||||
class InstructionFetch extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val jump_flag_id = Input(Bool())
|
||||
val jump_address_id = Input(UInt(Parameters.AddrWidth))
|
||||
val instruction_read_data = Input(UInt(Parameters.DataWidth))
|
||||
val instruction_valid = Input(Bool())
|
||||
|
||||
val instruction_address = Output(UInt(Parameters.AddrWidth))
|
||||
val instruction = Output(UInt(Parameters.InstructionWidth))
|
||||
})
|
||||
val pc = RegInit(ProgramCounter.EntryAddress)
|
||||
|
||||
when(io.instruction_valid) {
|
||||
io.instruction := io.instruction_read_data
|
||||
// lab1(InstructionFetch)
|
||||
|
||||
|
||||
|
||||
// la1(InstructionFetch) end
|
||||
|
||||
|
||||
}.otherwise{
|
||||
pc := pc
|
||||
io.instruction := 0x00000013.U
|
||||
}
|
||||
io.instruction_address := pc
|
||||
}
|
||||
106
lab1/src/main/scala/riscv/core/MemoryAccess.scala
Normal file
106
lab1/src/main/scala/riscv/core/MemoryAccess.scala
Normal file
@@ -0,0 +1,106 @@
|
||||
// Copyright 2022 Canbin Huang
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package riscv.core
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
import peripheral.RAMBundle
|
||||
import riscv.Parameters
|
||||
|
||||
class MemoryAccess extends Module {
|
||||
val io = IO(new Bundle() {
|
||||
val alu_result = Input(UInt(Parameters.DataWidth))
|
||||
val reg2_data = Input(UInt(Parameters.DataWidth))
|
||||
val memory_read_enable = Input(Bool())
|
||||
val memory_write_enable = Input(Bool())
|
||||
val funct3 = Input(UInt(3.W))
|
||||
|
||||
val wb_memory_read_data = Output(UInt(Parameters.DataWidth))
|
||||
|
||||
val memory_bundle = Flipped(new RAMBundle)
|
||||
})
|
||||
val mem_address_index = io.alu_result(log2Up(Parameters.WordSize) - 1, 0).asUInt
|
||||
|
||||
io.memory_bundle.write_enable := false.B
|
||||
io.memory_bundle.write_data := 0.U
|
||||
io.memory_bundle.address := io.alu_result
|
||||
io.memory_bundle.write_strobe := VecInit(Seq.fill(Parameters.WordSize)(false.B))
|
||||
io.wb_memory_read_data := 0.U
|
||||
|
||||
when(io.memory_read_enable) {
|
||||
val data = io.memory_bundle.read_data
|
||||
io.wb_memory_read_data := MuxLookup(
|
||||
io.funct3,
|
||||
0.U,
|
||||
IndexedSeq(
|
||||
InstructionsTypeL.lb -> MuxLookup(
|
||||
mem_address_index,
|
||||
Cat(Fill(24, data(31)), data(31, 24)),
|
||||
IndexedSeq(
|
||||
0.U -> Cat(Fill(24, data(7)), data(7, 0)),
|
||||
1.U -> Cat(Fill(24, data(15)), data(15, 8)),
|
||||
2.U -> Cat(Fill(24, data(23)), data(23, 16))
|
||||
)
|
||||
),
|
||||
InstructionsTypeL.lbu -> MuxLookup(
|
||||
mem_address_index,
|
||||
Cat(Fill(24, 0.U), data(31, 24)),
|
||||
IndexedSeq(
|
||||
0.U -> Cat(Fill(24, 0.U), data(7, 0)),
|
||||
1.U -> Cat(Fill(24, 0.U), data(15, 8)),
|
||||
2.U -> Cat(Fill(24, 0.U), data(23, 16))
|
||||
)
|
||||
),
|
||||
InstructionsTypeL.lh -> Mux(
|
||||
mem_address_index === 0.U,
|
||||
Cat(Fill(16, data(15)), data(15, 0)),
|
||||
Cat(Fill(16, data(31)), data(31, 16))
|
||||
|
||||
),
|
||||
InstructionsTypeL.lhu -> Mux(
|
||||
mem_address_index === 0.U,
|
||||
Cat(Fill(16, 0.U), data(15, 0)),
|
||||
Cat(Fill(16, 0.U), data(31, 16))
|
||||
),
|
||||
InstructionsTypeL.lw -> data
|
||||
)
|
||||
)
|
||||
}.elsewhen(io.memory_write_enable) {
|
||||
io.memory_bundle.write_data := io.reg2_data
|
||||
io.memory_bundle.write_enable := true.B
|
||||
io.memory_bundle.write_strobe := VecInit(Seq.fill(Parameters.WordSize)(false.B))
|
||||
when(io.funct3 === InstructionsTypeS.sb) {
|
||||
io.memory_bundle.write_strobe(mem_address_index) := true.B
|
||||
io.memory_bundle.write_data := io.reg2_data(Parameters.ByteBits, 0) << (mem_address_index << log2Up(Parameters.ByteBits).U)
|
||||
}.elsewhen(io.funct3 === InstructionsTypeS.sh) {
|
||||
when(mem_address_index === 0.U) {
|
||||
for (i <- 0 until Parameters.WordSize / 2) {
|
||||
io.memory_bundle.write_strobe(i) := true.B
|
||||
}
|
||||
io.memory_bundle.write_data := io.reg2_data(Parameters.WordSize / 2 * Parameters.ByteBits, 0)
|
||||
}.otherwise {
|
||||
for (i <- Parameters.WordSize / 2 until Parameters.WordSize) {
|
||||
io.memory_bundle.write_strobe(i) := true.B
|
||||
}
|
||||
io.memory_bundle.write_data := io.reg2_data(Parameters.WordSize / 2 * Parameters.ByteBits, 0) << (Parameters
|
||||
.WordSize / 2 * Parameters.ByteBits)
|
||||
}
|
||||
}.elsewhen(io.funct3 === InstructionsTypeS.sw) {
|
||||
for (i <- 0 until Parameters.WordSize) {
|
||||
io.memory_bundle.write_strobe(i) := true.B
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
70
lab1/src/main/scala/riscv/core/RegisterFile.scala
Normal file
70
lab1/src/main/scala/riscv/core/RegisterFile.scala
Normal file
@@ -0,0 +1,70 @@
|
||||
// Copyright 2021 Howard Lau
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package riscv.core
|
||||
|
||||
import chisel3._
|
||||
import riscv.Parameters
|
||||
|
||||
object Registers extends Enumeration {
|
||||
type Register = Value
|
||||
val zero,
|
||||
ra, sp, gp, tp,
|
||||
t0, t1, t2, fp,
|
||||
s1,
|
||||
a0, a1, a2, a3, a4, a5, a6, a7,
|
||||
s2, s3, s4, s5, s6, s7, s8, s9, s10, s11,
|
||||
t3, t4, t5, t6 = Value
|
||||
}
|
||||
|
||||
class RegisterFile extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val write_enable = Input(Bool())
|
||||
val write_address = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val write_data = Input(UInt(Parameters.DataWidth))
|
||||
|
||||
val read_address1 = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val read_address2 = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val read_data1 = Output(UInt(Parameters.DataWidth))
|
||||
val read_data2 = Output(UInt(Parameters.DataWidth))
|
||||
|
||||
val debug_read_address = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val debug_read_data = Output(UInt(Parameters.DataWidth))
|
||||
})
|
||||
val registers = RegInit(VecInit(Seq.fill(Parameters.PhysicalRegisters)(0.U(Parameters.DataWidth))))
|
||||
|
||||
when(!reset.asBool) {
|
||||
when(io.write_enable && io.write_address =/= 0.U) {
|
||||
registers(io.write_address) := io.write_data
|
||||
}
|
||||
}
|
||||
|
||||
io.read_data1 := Mux(
|
||||
io.read_address1 === 0.U,
|
||||
0.U,
|
||||
registers(io.read_address1)
|
||||
)
|
||||
|
||||
io.read_data2 := Mux(
|
||||
io.read_address2 === 0.U,
|
||||
0.U,
|
||||
registers(io.read_address2)
|
||||
)
|
||||
|
||||
io.debug_read_data := Mux(
|
||||
io.debug_read_address === 0.U,
|
||||
0.U,
|
||||
registers(io.debug_read_address)
|
||||
)
|
||||
}
|
||||
37
lab1/src/main/scala/riscv/core/WriteBack.scala
Normal file
37
lab1/src/main/scala/riscv/core/WriteBack.scala
Normal file
@@ -0,0 +1,37 @@
|
||||
// Copyright 2022 Canbin Huang
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package riscv.core
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
import riscv.Parameters
|
||||
|
||||
class WriteBack extends Module {
|
||||
val io = IO(new Bundle() {
|
||||
val instruction_address = Input(UInt(Parameters.AddrWidth))
|
||||
val alu_result = Input(UInt(Parameters.DataWidth))
|
||||
val memory_read_data = Input(UInt(Parameters.DataWidth))
|
||||
val regs_write_source = Input(UInt(2.W))
|
||||
val regs_write_data = Output(UInt(Parameters.DataWidth))
|
||||
})
|
||||
io.regs_write_data := MuxLookup(
|
||||
io.regs_write_source,
|
||||
io.alu_result,
|
||||
IndexedSeq(
|
||||
RegWriteSource.Memory -> io.memory_read_data,
|
||||
RegWriteSource.NextInstructionAddress -> (io.instruction_address + 4.U)
|
||||
)
|
||||
)
|
||||
}
|
||||
52
lab1/src/test/scala/riscv/TestAnnotations.scala
Normal file
52
lab1/src/test/scala/riscv/TestAnnotations.scala
Normal file
@@ -0,0 +1,52 @@
|
||||
// Copyright 2022 Howard Lau
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package riscv
|
||||
|
||||
import chiseltest.{VerilatorBackendAnnotation, WriteVcdAnnotation}
|
||||
import firrtl.AnnotationSeq
|
||||
|
||||
import java.nio.file.{Files, Paths}
|
||||
|
||||
object VerilatorEnabler {
|
||||
val annos: AnnotationSeq = if (sys.env.contains("Path")) {
|
||||
if (sys.env.getOrElse("Path", "").split(";").exists(path => {
|
||||
Files.exists(Paths.get(path, "verilator"))
|
||||
})) {
|
||||
Seq(VerilatorBackendAnnotation)
|
||||
} else{
|
||||
Seq()
|
||||
}
|
||||
} else {
|
||||
if (sys.env.getOrElse("PATH", "").split(":").exists(path => {
|
||||
Files.exists(Paths.get(path, "verilator"))
|
||||
})) {
|
||||
Seq(VerilatorBackendAnnotation)
|
||||
} else {
|
||||
Seq()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object WriteVcdEnabler {
|
||||
val annos: AnnotationSeq = if (sys.env.contains("WRITE_VCD")) {
|
||||
Seq(WriteVcdAnnotation)
|
||||
} else {
|
||||
Seq()
|
||||
}
|
||||
}
|
||||
|
||||
object TestAnnotations {
|
||||
val annos = VerilatorEnabler.annos ++ WriteVcdEnabler.annos
|
||||
}
|
||||
125
lab1/src/test/scala/riscv/singlecycle/CPUTest.scala
Normal file
125
lab1/src/test/scala/riscv/singlecycle/CPUTest.scala
Normal file
@@ -0,0 +1,125 @@
|
||||
// Copyright 2021 Howard Lau
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package riscv.singlecycle
|
||||
|
||||
|
||||
import chisel3._
|
||||
import chiseltest._
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import peripheral.{InstructionROM, Memory, ROMLoader}
|
||||
import riscv.core.{CPU, ProgramCounter}
|
||||
import riscv.{Parameters, TestAnnotations}
|
||||
|
||||
import java.nio.{ByteBuffer, ByteOrder}
|
||||
|
||||
|
||||
class TestTopModule(exeFilename: String) extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val mem_debug_read_address = Input(UInt(Parameters.AddrWidth))
|
||||
val regs_debug_read_address = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
|
||||
val regs_debug_read_data = Output(UInt(Parameters.DataWidth))
|
||||
val mem_debug_read_data = Output(UInt(Parameters.DataWidth))
|
||||
})
|
||||
|
||||
val mem = Module(new Memory(8192))
|
||||
val instruction_rom = Module(new InstructionROM(exeFilename))
|
||||
val rom_loader = Module(new ROMLoader(instruction_rom.capacity))
|
||||
|
||||
rom_loader.io.rom_data := instruction_rom.io.data
|
||||
rom_loader.io.load_address := Parameters.EntryAddress
|
||||
instruction_rom.io.address := rom_loader.io.rom_address
|
||||
|
||||
val CPU_clkdiv = RegInit(UInt(2.W), 0.U)
|
||||
val CPU_tick = Wire(Bool())
|
||||
val CPU_next = Wire(UInt(2.W))
|
||||
CPU_next := Mux(CPU_clkdiv === 3.U, 0.U, CPU_clkdiv + 1.U)
|
||||
CPU_tick := CPU_clkdiv === 0.U
|
||||
CPU_clkdiv := CPU_next
|
||||
|
||||
withClock(CPU_tick.asClock) {
|
||||
val cpu = Module(new CPU)
|
||||
cpu.io.debug_read_address := 0.U
|
||||
cpu.io.instruction_valid := rom_loader.io.load_finished
|
||||
mem.io.instruction_address := cpu.io.instruction_address
|
||||
cpu.io.instruction := mem.io.instruction
|
||||
|
||||
|
||||
when(!rom_loader.io.load_finished) {
|
||||
rom_loader.io.bundle <> mem.io.bundle
|
||||
cpu.io.memory_bundle.read_data := 0.U
|
||||
}.otherwise {
|
||||
rom_loader.io.bundle.read_data := 0.U
|
||||
cpu.io.memory_bundle <> mem.io.bundle
|
||||
}
|
||||
|
||||
cpu.io.debug_read_address := io.regs_debug_read_address
|
||||
io.regs_debug_read_data := cpu.io.debug_read_data
|
||||
}
|
||||
|
||||
mem.io.debug_read_address := io.mem_debug_read_address
|
||||
io.mem_debug_read_data := mem.io.debug_read_data
|
||||
}
|
||||
|
||||
|
||||
class FibonacciTest extends AnyFlatSpec with ChiselScalatestTester {
|
||||
behavior of "Single Cycle CPU"
|
||||
it should "calculate recursively fibonacci(10)" in {
|
||||
test(new TestTopModule("fibonacci.asmbin")).withAnnotations(TestAnnotations.annos) { c =>
|
||||
for (i <- 1 to 50) {
|
||||
c.clock.step(1000)
|
||||
c.io.mem_debug_read_address.poke((i * 4).U) // Avoid timeout
|
||||
}
|
||||
|
||||
c.io.mem_debug_read_address.poke(4.U)
|
||||
c.clock.step()
|
||||
c.io.mem_debug_read_data.expect(55.U)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class QuicksortTest extends AnyFlatSpec with ChiselScalatestTester {
|
||||
behavior of "Single Cycle CPU"
|
||||
it should "quicksort 10 numbers" in {
|
||||
test(new TestTopModule("quicksort.asmbin")).withAnnotations(TestAnnotations.annos) { c =>
|
||||
for (i <- 1 to 50) {
|
||||
c.clock.step(1000)
|
||||
c.io.mem_debug_read_address.poke((i * 4).U) // Avoid timeout
|
||||
}
|
||||
for (i <- 1 to 10) {
|
||||
c.io.mem_debug_read_address.poke((4 * i).U)
|
||||
c.clock.step()
|
||||
c.io.mem_debug_read_data.expect((i - 1).U)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ByteAccessTest extends AnyFlatSpec with ChiselScalatestTester {
|
||||
behavior of "Single Cycle CPU"
|
||||
it should "store and load single byte" in {
|
||||
test(new TestTopModule("sb.asmbin")).withAnnotations(TestAnnotations.annos) { c =>
|
||||
for (i <- 1 to 500) {
|
||||
c.clock.step()
|
||||
c.io.mem_debug_read_address.poke((i * 4).U) // Avoid timeout
|
||||
}
|
||||
c.io.regs_debug_read_address.poke(5.U)
|
||||
c.io.regs_debug_read_data.expect(0xDEADBEEFL.U)
|
||||
c.io.regs_debug_read_address.poke(6.U)
|
||||
c.io.regs_debug_read_data.expect(0xEF.U)
|
||||
c.io.regs_debug_read_address.poke(1.U)
|
||||
c.io.regs_debug_read_data.expect(0x15EF.U)
|
||||
}
|
||||
}
|
||||
}
|
||||
72
lab1/src/test/scala/riscv/singlecycle/ExecuteTest.scala
Normal file
72
lab1/src/test/scala/riscv/singlecycle/ExecuteTest.scala
Normal file
@@ -0,0 +1,72 @@
|
||||
// Copyright 2022 hrpccs
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package riscv.singlecycle
|
||||
|
||||
import chisel3._
|
||||
import chiseltest._
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import riscv.TestAnnotations
|
||||
import riscv.core.{ALUOp1Source, ALUOp2Source, Execute, InstructionTypes}
|
||||
|
||||
class ExecuteTest extends AnyFlatSpec with ChiselScalatestTester{
|
||||
behavior of "Exxecute of Single Cycle CPU"
|
||||
it should "execute correctly" in {
|
||||
test(new Execute).withAnnotations(TestAnnotations.annos) { c =>
|
||||
|
||||
// add test
|
||||
c.io.instruction.poke(0x001101b3L.U) //x3 = x2 + x1
|
||||
//c.io.immediate.poke(0.U)
|
||||
//c.io.aluop1_source.poke(0.U)
|
||||
//c.io.aluop2_source.poke(0.U)
|
||||
|
||||
var x = 0
|
||||
for (x <- 0 to 100) {
|
||||
val op1 = scala.util.Random.nextInt(429496729)
|
||||
val op2 = scala.util.Random.nextInt(429496729)
|
||||
val result = op1 + op2
|
||||
val addr = scala.util.Random.nextInt(32)
|
||||
|
||||
c.io.reg1_data.poke(op1.U)
|
||||
c.io.reg2_data.poke(op2.U)
|
||||
|
||||
c.clock.step()
|
||||
c.io.mem_alu_result.expect(result.U)
|
||||
c.io.if_jump_flag.expect(0.U)
|
||||
}
|
||||
|
||||
// beq test
|
||||
c.io.instruction.poke(0x00208163L.U) //pc + 2 if x1 === x2
|
||||
c.io.instruction_address.poke(2.U)
|
||||
c.io.immediate.poke(2.U)
|
||||
c.io.aluop1_source.poke(1.U)
|
||||
c.io.aluop2_source.poke(1.U)
|
||||
c.clock.step()
|
||||
|
||||
// equ
|
||||
c.io.reg1_data.poke(9.U)
|
||||
c.io.reg2_data.poke(9.U)
|
||||
c.clock.step()//add
|
||||
c.io.if_jump_flag.expect(1.U)
|
||||
c.io.if_jump_address.expect(4.U)
|
||||
|
||||
// not equ
|
||||
c.io.reg1_data.poke(9.U)
|
||||
c.io.reg2_data.poke(19.U)
|
||||
c.clock.step()
|
||||
c.io.if_jump_flag.expect(0.U)
|
||||
c.io.if_jump_address.expect(4.U)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
// Copyright 2022 hrpccs
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package riscv.singlecycle
|
||||
|
||||
import chisel3._
|
||||
import chiseltest._
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import riscv.TestAnnotations
|
||||
import riscv.core.{ALUOp1Source, ALUOp2Source, InstructionDecode, InstructionTypes}
|
||||
|
||||
class InstructionDecoderTest extends AnyFlatSpec with ChiselScalatestTester{
|
||||
behavior of "InstructionDecoder of Single Cycle CPU"
|
||||
it should "produce correct control signal" in {
|
||||
test(new InstructionDecode).withAnnotations(TestAnnotations.annos) { c =>
|
||||
c.io.instruction.poke(0x00a02223L.U) //S-type
|
||||
c.io.ex_aluop1_source.expect(ALUOp1Source.Register)
|
||||
c.io.ex_aluop2_source.expect(ALUOp2Source.Immediate)
|
||||
c.io.regs_reg1_read_address.expect(0.U)
|
||||
c.io.regs_reg2_read_address.expect(10.U)
|
||||
c.clock.step()
|
||||
|
||||
c.io.instruction.poke(0x000022b7L.U) //lui
|
||||
c.io.regs_reg1_read_address.expect(0.U)
|
||||
c.io.ex_aluop1_source.expect(ALUOp1Source.Register)
|
||||
c.io.ex_aluop2_source.expect(ALUOp2Source.Immediate)
|
||||
c.clock.step()
|
||||
|
||||
c.io.instruction.poke(0x002081b3L.U) //add
|
||||
c.io.ex_aluop1_source.expect(ALUOp1Source.Register)
|
||||
c.io.ex_aluop2_source.expect(ALUOp2Source.Register)
|
||||
c.clock.step()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
// Copyright 2022 hrpccs
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package riscv.singlecycle
|
||||
|
||||
import chisel3._
|
||||
import chiseltest._
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import riscv.TestAnnotations
|
||||
import riscv.Parameters
|
||||
import riscv.core.{ALUOp1Source, ALUOp2Source, InstructionFetch, InstructionTypes,ProgramCounter}
|
||||
|
||||
|
||||
import scala.math.pow
|
||||
import scala.util.Random
|
||||
|
||||
|
||||
|
||||
class InstructionFetchTest extends AnyFlatSpec with ChiselScalatestTester{
|
||||
behavior of "InstructionFetch of Single Cycle CPU"
|
||||
it should "fetch instruction" in {
|
||||
test(new InstructionFetch).withAnnotations(TestAnnotations.annos) { c =>
|
||||
val entry = 0x1000
|
||||
var pre = entry
|
||||
var cur = pre
|
||||
c.io.instruction_valid.poke(true.B)
|
||||
var x = 0
|
||||
for (x <- 0 to 100) {
|
||||
Random.nextInt(2) match {
|
||||
case 0 => // no jump
|
||||
cur = pre + 4
|
||||
c.io.jump_flag_id.poke(false.B)
|
||||
c.clock.step()
|
||||
c.io.instruction_address.expect(cur)
|
||||
pre = pre + 4
|
||||
case 1 => // jump
|
||||
c.io.jump_flag_id.poke(true.B)
|
||||
c.io.jump_address_id.poke(entry)
|
||||
c.clock.step()
|
||||
c.io.instruction_address.expect(entry)
|
||||
pre = entry
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
69
lab1/src/test/scala/riscv/singlecycle/RegisterFileTest.scala
Normal file
69
lab1/src/test/scala/riscv/singlecycle/RegisterFileTest.scala
Normal file
@@ -0,0 +1,69 @@
|
||||
// Copyright 2021 Howard Lau
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package riscv.singlecycle
|
||||
|
||||
import chisel3._
|
||||
import chiseltest._
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import riscv.TestAnnotations
|
||||
import riscv.core.RegisterFile
|
||||
|
||||
class RegisterFileTest extends AnyFlatSpec with ChiselScalatestTester {
|
||||
behavior of "Register File of Single Cycle CPU"
|
||||
it should "read the written content" in {
|
||||
test(new RegisterFile).withAnnotations(TestAnnotations.annos) { c =>
|
||||
timescope {
|
||||
c.io.write_enable.poke(true.B)
|
||||
c.io.write_address.poke(1.U)
|
||||
c.io.write_data.poke(0xDEADBEEFL.U)
|
||||
c.clock.step()
|
||||
}
|
||||
c.io.read_address1.poke(1.U)
|
||||
c.io.read_data1.expect(0xDEADBEEFL.U)
|
||||
}
|
||||
}
|
||||
|
||||
it should "x0 always be zero" in {
|
||||
test(new RegisterFile).withAnnotations(TestAnnotations.annos) { c =>
|
||||
timescope {
|
||||
c.io.write_enable.poke(true.B)
|
||||
c.io.write_address.poke(0.U)
|
||||
c.io.write_data.poke(0xDEADBEEFL.U)
|
||||
c.clock.step()
|
||||
}
|
||||
c.io.read_address1.poke(0.U)
|
||||
c.io.read_data1.expect(0.U)
|
||||
}
|
||||
}
|
||||
|
||||
it should "read the writing content" in {
|
||||
test(new RegisterFile).withAnnotations(TestAnnotations.annos) { c =>
|
||||
timescope {
|
||||
c.io.read_address1.poke(2.U)
|
||||
c.io.read_data1.expect(0.U)
|
||||
c.io.write_enable.poke(true.B)
|
||||
c.io.write_address.poke(2.U)
|
||||
c.io.write_data.poke(0xDEADBEEFL.U)
|
||||
c.clock.step()
|
||||
c.io.read_address1.poke(2.U)
|
||||
c.io.read_data1.expect(0xDEADBEEFL.U)
|
||||
c.clock.step()
|
||||
}
|
||||
c.io.read_address1.poke(2.U)
|
||||
c.io.read_data1.expect(0xDEADBEEFL.U)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
35
lab1/verilog/basys3/test.v
Normal file
35
lab1/verilog/basys3/test.v
Normal file
@@ -0,0 +1,35 @@
|
||||
`timescale 1ns / 1ps
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// Company:
|
||||
// Engineer:
|
||||
//
|
||||
// Create Date: 2021/12/17 16:31:05
|
||||
// Design Name:
|
||||
// Module Name: test
|
||||
// Project Name:
|
||||
// Target Devices:
|
||||
// Tool Versions:
|
||||
// Description:
|
||||
//
|
||||
// Dependencies:
|
||||
//
|
||||
// Revision:
|
||||
// Revision 0.01 - File Created
|
||||
// Additional Comments:
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
module test();
|
||||
reg clock;
|
||||
reg reset;
|
||||
initial begin
|
||||
clock = 0;
|
||||
forever #1 clock = ~clock;
|
||||
end
|
||||
initial begin
|
||||
reset = 1;
|
||||
#2 reset = 0;
|
||||
end
|
||||
Top top(clock, reset);
|
||||
endmodule
|
||||
221
lab1/verilog/pynq/TMDS_PLLVR.v
Normal file
221
lab1/verilog/pynq/TMDS_PLLVR.v
Normal file
@@ -0,0 +1,221 @@
|
||||
|
||||
// file: TMDS_PLLVR.v
|
||||
//
|
||||
// (c) Copyright 2008 - 2013 Xilinx, Inc. All rights reserved.
|
||||
//
|
||||
// This file contains confidential and proprietary information
|
||||
// of Xilinx, Inc. and is protected under U.S. and
|
||||
// international copyright and other intellectual property
|
||||
// laws.
|
||||
//
|
||||
// DISCLAIMER
|
||||
// This disclaimer is not a license and does not grant any
|
||||
// rights to the materials distributed herewith. Except as
|
||||
// otherwise provided in a valid license issued to you by
|
||||
// Xilinx, and to the maximum extent permitted by applicable
|
||||
// law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
|
||||
// WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
|
||||
// AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
|
||||
// BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
|
||||
// INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
|
||||
// (2) Xilinx shall not be liable (whether in contract or tort,
|
||||
// including negligence, or under any other theory of
|
||||
// liability) for any loss or damage of any kind or nature
|
||||
// related to, arising under or in connection with these
|
||||
// materials, including for any direct, or any indirect,
|
||||
// special, incidental, or consequential loss or damage
|
||||
// (including loss of data, profits, goodwill, or any type of
|
||||
// loss or damage suffered as a result of any action brought
|
||||
// by a third party) even if such damage or loss was
|
||||
// reasonably foreseeable or Xilinx had been advised of the
|
||||
// possibility of the same.
|
||||
//
|
||||
// CRITICAL APPLICATIONS
|
||||
// Xilinx products are not designed or intended to be fail-
|
||||
// safe, or for use in any application requiring fail-safe
|
||||
// performance, such as life-support or safety devices or
|
||||
// systems, Class III medical devices, nuclear facilities,
|
||||
// applications related to the deployment of airbags, or any
|
||||
// other applications that could lead to death, personal
|
||||
// injury, or severe property or environmental damage
|
||||
// (individually and collectively, "Critical
|
||||
// Applications"). Customer assumes the sole risk and
|
||||
// liability of any use of Xilinx products in Critical
|
||||
// Applications, subject only to applicable laws and
|
||||
// regulations governing limitations on product liability.
|
||||
//
|
||||
// THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
|
||||
// PART OF THIS FILE AT ALL TIMES.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// User entered comments
|
||||
//----------------------------------------------------------------------------
|
||||
// None
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Output Output Phase Duty Cycle Pk-to-Pk Phase
|
||||
// Clock Freq (MHz) (degrees) (%) Jitter (ps) Error (ps)
|
||||
//----------------------------------------------------------------------------
|
||||
// __clkout__250.00000______0.000______50.0______200.536____237.727
|
||||
// _clkoutd__100.00000______0.000______50.0______226.965____237.727
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Input Clock Freq (MHz) Input Jitter (UI)
|
||||
//----------------------------------------------------------------------------
|
||||
// __primary__________25.000____________0.010
|
||||
|
||||
`timescale 1ps/1ps
|
||||
|
||||
(* CORE_GENERATION_INFO = "TMDS_PLLVR,clk_wiz_v6_0_5_0_0,{component_name=TMDS_PLLVR,use_phase_alignment=true,use_min_o_jitter=false,use_max_i_jitter=false,use_dyn_phase_shift=false,use_inclk_switchover=false,use_dyn_reconfig=false,enable_axi=0,feedback_source=FDBK_AUTO,PRIMITIVE=PLL,num_out_clk=2,clkin1_period=40.000,clkin2_period=10.0,use_power_down=false,use_reset=true,use_locked=true,use_inclk_stopped=false,feedback_type=SINGLE,CLOCK_MGR_TYPE=NA,manual_override=true}" *)
|
||||
|
||||
module TMDS_PLLVR
|
||||
(
|
||||
// Clock out ports
|
||||
output clkout,
|
||||
output clkoutd,
|
||||
// Status and control signals
|
||||
input reset,
|
||||
output lock,
|
||||
// Clock in ports
|
||||
input clkin
|
||||
);
|
||||
|
||||
TMDS_PLLVR_clk_wiz inst
|
||||
(
|
||||
// Clock out ports
|
||||
.clkout(clkout),
|
||||
.clkoutd(clkoutd),
|
||||
// Status and control signals
|
||||
.reset(reset),
|
||||
.lock(lock),
|
||||
// Clock in ports
|
||||
.clk_in1(clkin)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
module TMDS_PLLVR_clk_wiz
|
||||
|
||||
(// Clock in ports
|
||||
// Clock out ports
|
||||
output clkout,
|
||||
output clkoutd,
|
||||
// Status and control signals
|
||||
input reset,
|
||||
output lock,
|
||||
input clk_in1
|
||||
);
|
||||
// Input buffering
|
||||
//------------------------------------
|
||||
wire clk_in1_TMDS_PLLVR;
|
||||
wire clk_in2_TMDS_PLLVR;
|
||||
IBUF clkin1_ibufg
|
||||
(.O (clk_in1_TMDS_PLLVR),
|
||||
.I (clk_in1));
|
||||
|
||||
|
||||
|
||||
|
||||
// Clocking PRIMITIVE
|
||||
//------------------------------------
|
||||
|
||||
// Instantiation of the MMCM PRIMITIVE
|
||||
// * Unused inputs are tied off
|
||||
// * Unused outputs are labeled unused
|
||||
|
||||
wire clkout_TMDS_PLLVR;
|
||||
wire clkoutd_TMDS_PLLVR;
|
||||
wire clk_out3_TMDS_PLLVR;
|
||||
wire clk_out4_TMDS_PLLVR;
|
||||
wire clk_out5_TMDS_PLLVR;
|
||||
wire clk_out6_TMDS_PLLVR;
|
||||
wire clk_out7_TMDS_PLLVR;
|
||||
|
||||
wire [15:0] do_unused;
|
||||
wire drdy_unused;
|
||||
wire psdone_unused;
|
||||
wire lock_int;
|
||||
wire clkfbout_TMDS_PLLVR;
|
||||
wire clkfbout_buf_TMDS_PLLVR;
|
||||
wire clkfboutb_unused;
|
||||
wire clkout2_unused;
|
||||
wire clkout3_unused;
|
||||
wire clkout4_unused;
|
||||
wire clkout5_unused;
|
||||
wire clkout6_unused;
|
||||
wire clkfbstopped_unused;
|
||||
wire clkinstopped_unused;
|
||||
wire reset_high;
|
||||
|
||||
PLLE2_ADV
|
||||
#(.BANDWIDTH ("OPTIMIZED"),
|
||||
.COMPENSATION ("ZHOLD"),
|
||||
.STARTUP_WAIT ("FALSE"),
|
||||
.DIVCLK_DIVIDE (1),
|
||||
.CLKFBOUT_MULT (40),
|
||||
.CLKFBOUT_PHASE (0.000),
|
||||
.CLKOUT0_DIVIDE (4),
|
||||
.CLKOUT0_PHASE (0.000),
|
||||
.CLKOUT0_DUTY_CYCLE (0.500),
|
||||
.CLKOUT1_DIVIDE (10),
|
||||
.CLKOUT1_PHASE (0.000),
|
||||
.CLKOUT1_DUTY_CYCLE (0.500),
|
||||
.CLKIN1_PERIOD (40.000))
|
||||
plle2_adv_inst
|
||||
// Output clocks
|
||||
(
|
||||
.CLKFBOUT (clkfbout_TMDS_PLLVR),
|
||||
.CLKOUT0 (clkout_TMDS_PLLVR),
|
||||
.CLKOUT1 (clkoutd_TMDS_PLLVR),
|
||||
.CLKOUT2 (clkout2_unused),
|
||||
.CLKOUT3 (clkout3_unused),
|
||||
.CLKOUT4 (clkout4_unused),
|
||||
.CLKOUT5 (clkout5_unused),
|
||||
// Input clock control
|
||||
.CLKFBIN (clkfbout_buf_TMDS_PLLVR),
|
||||
.CLKIN1 (clk_in1_TMDS_PLLVR),
|
||||
.CLKIN2 (1'b0),
|
||||
// Tied to always select the primary input clock
|
||||
.CLKINSEL (1'b1),
|
||||
// Ports for dynamic reconfiguration
|
||||
.DADDR (7'h0),
|
||||
.DCLK (1'b0),
|
||||
.DEN (1'b0),
|
||||
.DI (16'h0),
|
||||
.DO (do_unused),
|
||||
.DRDY (drdy_unused),
|
||||
.DWE (1'b0),
|
||||
// Other control and status signals
|
||||
.LOCKED (lock_int),
|
||||
.PWRDWN (1'b0),
|
||||
.RST (reset_high));
|
||||
assign reset_high = reset;
|
||||
|
||||
assign lock = lock_int;
|
||||
// Clock Monitor clock assigning
|
||||
//--------------------------------------
|
||||
// Output buffering
|
||||
//-----------------------------------
|
||||
|
||||
BUFG clkf_buf
|
||||
(.O (clkfbout_buf_TMDS_PLLVR),
|
||||
.I (clkfbout_TMDS_PLLVR));
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
BUFG clkout1_buf
|
||||
(.O (clkout),
|
||||
.I (clkout_TMDS_PLLVR));
|
||||
|
||||
|
||||
BUFG clkout2_buf
|
||||
(.O (clkoutd),
|
||||
.I (clkoutd_TMDS_PLLVR));
|
||||
|
||||
|
||||
|
||||
endmodule
|
||||
136
lab1/verilog/pynq/design_1_wrapper.v
Normal file
136
lab1/verilog/pynq/design_1_wrapper.v
Normal file
@@ -0,0 +1,136 @@
|
||||
//Copyright 1986-2020 Xilinx, Inc. All Rights Reserved.
|
||||
//--------------------------------------------------------------------------------
|
||||
//Tool Version: Vivado v.2020.1 (win64) Build 2902540 Wed May 27 19:54:49 MDT 2020
|
||||
//Date : Thu Jun 9 10:53:21 2022
|
||||
//Host : DESKTOP-UR8AHA2 running 64-bit major release (build 9200)
|
||||
//Command : generate_target design_1_wrapper.bd
|
||||
//Design : design_1_wrapper
|
||||
//Purpose : IP block netlist
|
||||
//--------------------------------------------------------------------------------
|
||||
`timescale 1 ps / 1 ps
|
||||
|
||||
module design_1_wrapper
|
||||
(DDR_addr,
|
||||
DDR_ba,
|
||||
DDR_cas_n,
|
||||
DDR_ck_n,
|
||||
DDR_ck_p,
|
||||
DDR_cke,
|
||||
DDR_cs_n,
|
||||
DDR_dm,
|
||||
DDR_dq,
|
||||
DDR_dqs_n,
|
||||
DDR_dqs_p,
|
||||
DDR_odt,
|
||||
DDR_ras_n,
|
||||
DDR_reset_n,
|
||||
DDR_we_n,
|
||||
FIXED_IO_ddr_vrn,
|
||||
FIXED_IO_ddr_vrp,
|
||||
FIXED_IO_mio,
|
||||
FIXED_IO_ps_clk,
|
||||
FIXED_IO_ps_porb,
|
||||
FIXED_IO_ps_srstb,
|
||||
io_hdmi_clk_n,
|
||||
io_hdmi_clk_p,
|
||||
io_hdmi_data_n,
|
||||
io_hdmi_data_p,
|
||||
io_hdmi_hpdn,
|
||||
io_led,
|
||||
io_rx,
|
||||
io_tx,
|
||||
reset);
|
||||
inout [14:0]DDR_addr;
|
||||
inout [2:0]DDR_ba;
|
||||
inout DDR_cas_n;
|
||||
inout DDR_ck_n;
|
||||
inout DDR_ck_p;
|
||||
inout DDR_cke;
|
||||
inout DDR_cs_n;
|
||||
inout [3:0]DDR_dm;
|
||||
inout [31:0]DDR_dq;
|
||||
inout [3:0]DDR_dqs_n;
|
||||
inout [3:0]DDR_dqs_p;
|
||||
inout DDR_odt;
|
||||
inout DDR_ras_n;
|
||||
inout DDR_reset_n;
|
||||
inout DDR_we_n;
|
||||
inout FIXED_IO_ddr_vrn;
|
||||
inout FIXED_IO_ddr_vrp;
|
||||
inout [53:0]FIXED_IO_mio;
|
||||
inout FIXED_IO_ps_clk;
|
||||
inout FIXED_IO_ps_porb;
|
||||
inout FIXED_IO_ps_srstb;
|
||||
output io_hdmi_clk_n;
|
||||
output io_hdmi_clk_p;
|
||||
output [2:0]io_hdmi_data_n;
|
||||
output [2:0]io_hdmi_data_p;
|
||||
output io_hdmi_hpdn;
|
||||
output [3:0]io_led;
|
||||
input io_rx;
|
||||
output io_tx;
|
||||
input reset;
|
||||
|
||||
wire [14:0]DDR_addr;
|
||||
wire [2:0]DDR_ba;
|
||||
wire DDR_cas_n;
|
||||
wire DDR_ck_n;
|
||||
wire DDR_ck_p;
|
||||
wire DDR_cke;
|
||||
wire DDR_cs_n;
|
||||
wire [3:0]DDR_dm;
|
||||
wire [31:0]DDR_dq;
|
||||
wire [3:0]DDR_dqs_n;
|
||||
wire [3:0]DDR_dqs_p;
|
||||
wire DDR_odt;
|
||||
wire DDR_ras_n;
|
||||
wire DDR_reset_n;
|
||||
wire DDR_we_n;
|
||||
wire FIXED_IO_ddr_vrn;
|
||||
wire FIXED_IO_ddr_vrp;
|
||||
wire [53:0]FIXED_IO_mio;
|
||||
wire FIXED_IO_ps_clk;
|
||||
wire FIXED_IO_ps_porb;
|
||||
wire FIXED_IO_ps_srstb;
|
||||
wire io_hdmi_clk_n;
|
||||
wire io_hdmi_clk_p;
|
||||
wire [2:0]io_hdmi_data_n;
|
||||
wire [2:0]io_hdmi_data_p;
|
||||
wire io_hdmi_hpdn;
|
||||
wire [3:0]io_led;
|
||||
wire io_rx;
|
||||
wire io_tx;
|
||||
wire reset;
|
||||
|
||||
design_1 design_1_i
|
||||
(.DDR_addr(DDR_addr),
|
||||
.DDR_ba(DDR_ba),
|
||||
.DDR_cas_n(DDR_cas_n),
|
||||
.DDR_ck_n(DDR_ck_n),
|
||||
.DDR_ck_p(DDR_ck_p),
|
||||
.DDR_cke(DDR_cke),
|
||||
.DDR_cs_n(DDR_cs_n),
|
||||
.DDR_dm(DDR_dm),
|
||||
.DDR_dq(DDR_dq),
|
||||
.DDR_dqs_n(DDR_dqs_n),
|
||||
.DDR_dqs_p(DDR_dqs_p),
|
||||
.DDR_odt(DDR_odt),
|
||||
.DDR_ras_n(DDR_ras_n),
|
||||
.DDR_reset_n(DDR_reset_n),
|
||||
.DDR_we_n(DDR_we_n),
|
||||
.FIXED_IO_ddr_vrn(FIXED_IO_ddr_vrn),
|
||||
.FIXED_IO_ddr_vrp(FIXED_IO_ddr_vrp),
|
||||
.FIXED_IO_mio(FIXED_IO_mio),
|
||||
.FIXED_IO_ps_clk(FIXED_IO_ps_clk),
|
||||
.FIXED_IO_ps_porb(FIXED_IO_ps_porb),
|
||||
.FIXED_IO_ps_srstb(FIXED_IO_ps_srstb),
|
||||
.io_hdmi_clk_n(io_hdmi_clk_n),
|
||||
.io_hdmi_clk_p(io_hdmi_clk_p),
|
||||
.io_hdmi_data_n(io_hdmi_data_n),
|
||||
.io_hdmi_data_p(io_hdmi_data_p),
|
||||
.io_hdmi_hpdn(io_hdmi_hpdn),
|
||||
.io_led(io_led),
|
||||
.io_rx(io_rx),
|
||||
.io_tx(io_tx),
|
||||
.reset(reset));
|
||||
endmodule
|
||||
35
lab1/verilog/pynq/test.v
Normal file
35
lab1/verilog/pynq/test.v
Normal file
@@ -0,0 +1,35 @@
|
||||
`timescale 1ns / 1ps
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// Company:
|
||||
// Engineer:
|
||||
//
|
||||
// Create Date: 2021/12/17 16:31:05
|
||||
// Design Name:
|
||||
// Module Name: test
|
||||
// Project Name:
|
||||
// Target Devices:
|
||||
// Tool Versions:
|
||||
// Description:
|
||||
//
|
||||
// Dependencies:
|
||||
//
|
||||
// Revision:
|
||||
// Revision 0.01 - File Created
|
||||
// Additional Comments:
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
module test();
|
||||
reg clock;
|
||||
reg reset;
|
||||
initial begin
|
||||
clock = 0;
|
||||
forever #1 clock = ~clock;
|
||||
end
|
||||
initial begin
|
||||
reset = 1;
|
||||
#2 reset = 0;
|
||||
end
|
||||
Top top(clock, reset);
|
||||
endmodule
|
||||
245
lab1/verilog/verilator/sim_main.cpp
Normal file
245
lab1/verilog/verilator/sim_main.cpp
Normal file
@@ -0,0 +1,245 @@
|
||||
#include <verilated.h>
|
||||
#include <verilated_vcd_c.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "VTop.h" // From Verilating "top.v"
|
||||
|
||||
|
||||
class Memory {
|
||||
std::vector<uint32_t> memory;
|
||||
|
||||
public:
|
||||
Memory(size_t size) : memory(size, 0) {}
|
||||
uint32_t read(size_t address) {
|
||||
address = address / 4;
|
||||
if (address >= memory.size()) {
|
||||
// printf("invalid read address 0x%08x\n", address * 4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return memory[address];
|
||||
}
|
||||
|
||||
uint32_t readInst(size_t address) {
|
||||
address = address / 4;
|
||||
if (address >= memory.size()) {
|
||||
// printf("invalid read Inst address 0x%08x\n", address * 4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return memory[address];
|
||||
}
|
||||
|
||||
void write(size_t address, uint32_t value, bool write_strobe[4]) {
|
||||
address = address / 4;
|
||||
uint32_t write_mask = 0;
|
||||
if (write_strobe[0]) write_mask |= 0x000000FF;
|
||||
if (write_strobe[1]) write_mask |= 0x0000FF00;
|
||||
if (write_strobe[2]) write_mask |= 0x00FF0000;
|
||||
if (write_strobe[3]) write_mask |= 0xFF000000;
|
||||
if (address >= memory.size()) {
|
||||
// printf("invalid write address 0x%08x\n", address * 4);
|
||||
return;
|
||||
}
|
||||
memory[address] = (memory[address] & ~write_mask) | (value & write_mask);
|
||||
}
|
||||
|
||||
void load_binary(std::string const& filename, size_t load_address = 0x1000) {
|
||||
std::ifstream file(filename, std::ios::binary);
|
||||
if (!file) {
|
||||
throw std::runtime_error("Could not open file " + filename);
|
||||
}
|
||||
file.seekg(0, std::ios::end);
|
||||
size_t size = file.tellg();
|
||||
if (load_address + size > memory.size() * 4) {
|
||||
throw std::runtime_error("File " + filename + " is too large (File is " +
|
||||
std::to_string(size) + " bytes. Memory is " +
|
||||
std::to_string(memory.size() * 4 - load_address) + " bytes.)");
|
||||
}
|
||||
file.seekg(0, std::ios::beg);
|
||||
for (int i = 0; i < size / 4; ++i) {
|
||||
file.read(reinterpret_cast<char*>(&memory[i + load_address / 4]),
|
||||
sizeof(uint32_t));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class VCDTracer {
|
||||
VerilatedVcdC* tfp = nullptr;
|
||||
|
||||
public:
|
||||
void enable(std::string const& filename, VTop& top) {
|
||||
Verilated::traceEverOn(true);
|
||||
tfp = new VerilatedVcdC;
|
||||
top.trace(tfp, 99);
|
||||
tfp->open(filename.c_str());
|
||||
tfp->set_time_resolution("1ps");
|
||||
tfp->set_time_unit("1ns");
|
||||
if (!tfp->isOpen()) {
|
||||
throw std::runtime_error("Failed to open VCD dump file " + filename);
|
||||
}
|
||||
}
|
||||
|
||||
void dump(vluint64_t time) {
|
||||
if (tfp) {
|
||||
tfp->dump(time);
|
||||
}
|
||||
}
|
||||
|
||||
~VCDTracer() {
|
||||
if (tfp) {
|
||||
tfp->close();
|
||||
delete tfp;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
uint32_t parse_number(std::string const& str) {
|
||||
if (str.size() > 2) {
|
||||
auto&& prefix = str.substr(0, 2);
|
||||
if (prefix == "0x" || prefix == "0X") {
|
||||
return std::stoul(str.substr(2), nullptr, 16);
|
||||
}
|
||||
}
|
||||
return std::stoul(str);
|
||||
}
|
||||
|
||||
class Simulator {
|
||||
vluint64_t main_time = 0;
|
||||
vluint64_t max_sim_time = 10000;
|
||||
uint32_t halt_address = 0;
|
||||
size_t memory_words = 1024 * 1024; // 4MB
|
||||
bool dump_vcd = false;
|
||||
std::unique_ptr<VTop> top;
|
||||
std::unique_ptr<VCDTracer> vcd_tracer;
|
||||
std::unique_ptr<Memory> memory;
|
||||
bool dump_signature = false;
|
||||
unsigned long signature_begin, signature_end;
|
||||
std::string signature_filename;
|
||||
std::string instruction_filename;
|
||||
|
||||
public:
|
||||
void parse_args(std::vector<std::string> const& args) {
|
||||
if (auto it = std::find(args.begin(), args.end(), "-halt");
|
||||
it != args.end()) {
|
||||
halt_address = parse_number(*(it + 1));
|
||||
}
|
||||
|
||||
if (auto it = std::find(args.begin(), args.end(), "-memory");
|
||||
it != args.end()) {
|
||||
memory_words = std::stoul(*(it + 1));
|
||||
}
|
||||
|
||||
if (auto it = std::find(args.begin(), args.end(), "-time");
|
||||
it != args.end()) {
|
||||
max_sim_time = std::stoul(*(it + 1));
|
||||
}
|
||||
|
||||
if (auto it = std::find(args.begin(), args.end(), "-vcd");
|
||||
it != args.end()) {
|
||||
vcd_tracer->enable(*(it + 1), *top);
|
||||
}
|
||||
|
||||
if (auto it = std::find(args.begin(), args.end(), "-signature");
|
||||
it != args.end()) {
|
||||
dump_signature = true;
|
||||
signature_begin = parse_number(*(it + 1));
|
||||
signature_end = parse_number(*(it + 2));
|
||||
signature_filename = *(it + 3);
|
||||
}
|
||||
|
||||
if (auto it = std::find(args.begin(), args.end(), "-instruction");
|
||||
it != args.end()) {
|
||||
instruction_filename = *(it + 1);
|
||||
}
|
||||
}
|
||||
|
||||
Simulator(std::vector<std::string> const& args)
|
||||
: top(std::make_unique<VTop>()),
|
||||
vcd_tracer(std::make_unique<VCDTracer>()) {
|
||||
parse_args(args);
|
||||
memory = std::make_unique<Memory>(memory_words);
|
||||
if (!instruction_filename.empty()) {
|
||||
memory->load_binary(instruction_filename);
|
||||
}
|
||||
}
|
||||
|
||||
void run() {
|
||||
top->reset = 1;
|
||||
top->clock = 0;
|
||||
top->eval();
|
||||
vcd_tracer->dump(main_time);
|
||||
uint32_t data_memory_read_word = 0;
|
||||
uint32_t inst_memory_read_word = 0;
|
||||
uint32_t counter = 0;
|
||||
uint32_t clocktime = 1;
|
||||
bool memory_write_strobe[4] = {false};
|
||||
while (main_time < max_sim_time && !Verilated::gotFinish()) {
|
||||
++main_time;
|
||||
++counter;
|
||||
if(counter > clocktime){
|
||||
top->clock = !top->clock;
|
||||
counter = 0;
|
||||
}
|
||||
if (main_time > 2) {
|
||||
top->reset = 0;
|
||||
}
|
||||
// top->io_mem_slave_read_data = memory_read_word;
|
||||
top->io_instruction_valid = 1;
|
||||
top->io_memory_bundle_read_data = data_memory_read_word;
|
||||
top->io_instruction = inst_memory_read_word;
|
||||
top->clock = !top->clock;
|
||||
top->eval();
|
||||
|
||||
|
||||
data_memory_read_word = memory->read(top->io_memory_bundle_address);
|
||||
|
||||
|
||||
inst_memory_read_word = memory->readInst(top->io_instruction_address);
|
||||
|
||||
if (top->io_memory_bundle_write_enable) {
|
||||
memory_write_strobe[0] = top->io_memory_bundle_write_strobe_0;
|
||||
memory_write_strobe[1] = top->io_memory_bundle_write_strobe_1;
|
||||
memory_write_strobe[2] = top->io_memory_bundle_write_strobe_2;
|
||||
memory_write_strobe[3] = top->io_memory_bundle_write_strobe_3;
|
||||
memory->write(top->io_memory_bundle_address, top->io_memory_bundle_write_data,
|
||||
memory_write_strobe);
|
||||
}
|
||||
vcd_tracer->dump(main_time);
|
||||
if (halt_address) {
|
||||
if (memory->read(halt_address) == 0xBABECAFE) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dump_signature) {
|
||||
char data[9] = {0};
|
||||
std::ofstream signature_file(signature_filename);
|
||||
for (size_t addr = signature_begin; addr < signature_end; addr += 4) {
|
||||
snprintf(data, 9, "%08x", memory->read(addr));
|
||||
signature_file << data << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~Simulator() {
|
||||
if (top) {
|
||||
top->final();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
Verilated::commandArgs(argc, argv);
|
||||
std::vector<std::string> args(argv, argv + argc);
|
||||
Simulator simulator(args);
|
||||
simulator.run();
|
||||
return 0;
|
||||
}
|
||||
307
lab1/vivado/basys3/basys3.xdc
Normal file
307
lab1/vivado/basys3/basys3.xdc
Normal file
@@ -0,0 +1,307 @@
|
||||
# Copyright 2021 Howard Lau
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
## Clock signal
|
||||
set_property PACKAGE_PIN W5 [get_ports clock]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports clock]
|
||||
create_clock -add -name sys_clk_pin -period 20.00 -waveform {0 5} [get_ports clock]
|
||||
|
||||
## Switches
|
||||
set_property PACKAGE_PIN V17 [get_ports {io_switch[0]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_switch[0]}]
|
||||
set_property PACKAGE_PIN V16 [get_ports {io_switch[1]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_switch[1]}]
|
||||
set_property PACKAGE_PIN W16 [get_ports {io_switch[2]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_switch[2]}]
|
||||
set_property PACKAGE_PIN W17 [get_ports {io_switch[3]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_switch[3]}]
|
||||
set_property PACKAGE_PIN W15 [get_ports {io_switch[4]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_switch[4]}]
|
||||
set_property PACKAGE_PIN V15 [get_ports {io_switch[5]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_switch[5]}]
|
||||
set_property PACKAGE_PIN W14 [get_ports {io_switch[6]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_switch[6]}]
|
||||
set_property PACKAGE_PIN W13 [get_ports {io_switch[7]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_switch[7]}]
|
||||
set_property PACKAGE_PIN V2 [get_ports {io_switch[8]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_switch[8]}]
|
||||
set_property PACKAGE_PIN T3 [get_ports {io_switch[9]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_switch[9]}]
|
||||
set_property PACKAGE_PIN T2 [get_ports {io_switch[10]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_switch[10]}]
|
||||
set_property PACKAGE_PIN R3 [get_ports {io_switch[11]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_switch[11]}]
|
||||
set_property PACKAGE_PIN W2 [get_ports {io_switch[12]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_switch[12]}]
|
||||
set_property PACKAGE_PIN U1 [get_ports {io_switch[13]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_switch[13]}]
|
||||
set_property PACKAGE_PIN T1 [get_ports {io_switch[14]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_switch[14]}]
|
||||
set_property PACKAGE_PIN R2 [get_ports {io_switch[15]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_switch[15]}]
|
||||
|
||||
|
||||
## LEDs
|
||||
set_property PACKAGE_PIN U16 [get_ports {io_led[0]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_led[0]}]
|
||||
set_property PACKAGE_PIN E19 [get_ports {io_led[1]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_led[1]}]
|
||||
set_property PACKAGE_PIN U19 [get_ports {io_led[2]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_led[2]}]
|
||||
set_property PACKAGE_PIN V19 [get_ports {io_led[3]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_led[3]}]
|
||||
set_property PACKAGE_PIN W18 [get_ports {io_led[4]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_led[4]}]
|
||||
set_property PACKAGE_PIN U15 [get_ports {io_led[5]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_led[5]}]
|
||||
set_property PACKAGE_PIN U14 [get_ports {io_led[6]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_led[6]}]
|
||||
set_property PACKAGE_PIN V14 [get_ports {io_led[7]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_led[7]}]
|
||||
set_property PACKAGE_PIN V13 [get_ports {io_led[8]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_led[8]}]
|
||||
set_property PACKAGE_PIN V3 [get_ports {io_led[9]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_led[9]}]
|
||||
set_property PACKAGE_PIN W3 [get_ports {io_led[10]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_led[10]}]
|
||||
set_property PACKAGE_PIN U3 [get_ports {io_led[11]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_led[11]}]
|
||||
set_property PACKAGE_PIN P3 [get_ports {io_led[12]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_led[12]}]
|
||||
set_property PACKAGE_PIN N3 [get_ports {io_led[13]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_led[13]}]
|
||||
set_property PACKAGE_PIN P1 [get_ports {io_led[14]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_led[14]}]
|
||||
set_property PACKAGE_PIN L1 [get_ports {io_led[15]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_led[15]}]
|
||||
|
||||
|
||||
##7 segment display
|
||||
set_property PACKAGE_PIN U7 [get_ports io_segs[0]]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports io_segs[0]]
|
||||
set_property PACKAGE_PIN V5 [get_ports io_segs[1]]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports io_segs[1]]
|
||||
set_property PACKAGE_PIN U5 [get_ports io_segs[2]]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports io_segs[2]]
|
||||
set_property PACKAGE_PIN V8 [get_ports io_segs[3]]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports io_segs[3]]
|
||||
set_property PACKAGE_PIN U8 [get_ports io_segs[4]]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports io_segs[4]]
|
||||
set_property PACKAGE_PIN W6 [get_ports io_segs[5]]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports io_segs[5]]
|
||||
set_property PACKAGE_PIN W7 [get_ports io_segs[6]]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports io_segs[6]]
|
||||
set_property PACKAGE_PIN V7 [get_ports io_segs[7]]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports io_segs[7]]
|
||||
|
||||
set_property PACKAGE_PIN U2 [get_ports {io_digit_mask[0]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_digit_mask[0]}]
|
||||
set_property PACKAGE_PIN U4 [get_ports {io_digit_mask[1]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_digit_mask[1]}]
|
||||
set_property PACKAGE_PIN V4 [get_ports {io_digit_mask[2]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_digit_mask[2]}]
|
||||
set_property PACKAGE_PIN W4 [get_ports {io_digit_mask[3]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_digit_mask[3]}]
|
||||
|
||||
|
||||
##Buttons
|
||||
set_property PACKAGE_PIN U18 [get_ports reset]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports reset]
|
||||
#set_property PACKAGE_PIN T18 [get_ports io_freqIncrease]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports io_freqIncrease]
|
||||
#set_property PACKAGE_PIN W19 [get_ports io_widthIncrease]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports io_widthIncrease]
|
||||
#set_property PACKAGE_PIN T17 [get_ports io_widthDecrease]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports io_widthDecrease]
|
||||
#set_property PACKAGE_PIN U17 [get_ports io_freqDecrease]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports io_freqDecrease]
|
||||
|
||||
|
||||
|
||||
##Pmod Header JA
|
||||
##Sch name = JA1
|
||||
#set_property PACKAGE_PIN J1 [get_ports {JA[0]}]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports {JA[0]}]
|
||||
##Sch name = JA2
|
||||
#set_property PACKAGE_PIN L2 [get_ports {JA[1]}]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports {JA[1]}]
|
||||
##Sch name = JA3
|
||||
#set_property PACKAGE_PIN J2 [get_ports {JA[2]}]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports {JA[2]}]
|
||||
##Sch name = JA4
|
||||
#set_property PACKAGE_PIN G2 [get_ports {JA[3]}]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports {JA[3]}]
|
||||
##Sch name = JA7
|
||||
#set_property PACKAGE_PIN H1 [get_ports {JA[4]}]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports {JA[4]}]
|
||||
##Sch name = JA8
|
||||
#set_property PACKAGE_PIN K2 [get_ports {JA[5]}]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports {JA[5]}]
|
||||
##Sch name = JA9
|
||||
#set_property PACKAGE_PIN H2 [get_ports {JA[6]}]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports {JA[6]}]
|
||||
##Sch name = JA10
|
||||
#set_property PACKAGE_PIN G3 [get_ports {JA[7]}]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports {JA[7]}]
|
||||
|
||||
|
||||
|
||||
##Pmod Header JB
|
||||
##Sch name = JB1
|
||||
#set_property PACKAGE_PIN A14 [get_ports {JB[0]}]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports {JB[0]}]
|
||||
##Sch name = JB2
|
||||
#set_property PACKAGE_PIN A16 [get_ports {JB[1]}]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports {JB[1]}]
|
||||
##Sch name = JB3
|
||||
#set_property PACKAGE_PIN B15 [get_ports {JB[2]}]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports {JB[2]}]
|
||||
##Sch name = JB4
|
||||
#set_property PACKAGE_PIN B16 [get_ports {JB[3]}]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports {JB[3]}]
|
||||
##Sch name = JB7
|
||||
#set_property PACKAGE_PIN A15 [get_ports {JB[4]}]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports {JB[4]}]
|
||||
##Sch name = JB8
|
||||
#set_property PACKAGE_PIN A17 [get_ports {JB[5]}]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports {JB[5]}]
|
||||
##Sch name = JB9
|
||||
#set_property PACKAGE_PIN C15 [get_ports {JB[6]}]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports {JB[6]}]
|
||||
##Sch name = JB10
|
||||
#set_property PACKAGE_PIN C16 [get_ports {JB[7]}]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports {JB[7]}]
|
||||
|
||||
|
||||
|
||||
##Pmod Header JC
|
||||
##Sch name = JC1
|
||||
#set_property PACKAGE_PIN K17 [get_ports {JC[0]}]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports {JC[0]}]
|
||||
##Sch name = JC2
|
||||
#set_property PACKAGE_PIN M18 [get_ports {JC[1]}]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports {JC[1]}]
|
||||
##Sch name = JC3
|
||||
#set_property PACKAGE_PIN N17 [get_ports {JC[2]}]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports {JC[2]}]
|
||||
##Sch name = JC4
|
||||
#set_property PACKAGE_PIN P18 [get_ports {JC[3]}]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports {JC[3]}]
|
||||
##Sch name = JC7
|
||||
#set_property PACKAGE_PIN L17 [get_ports {JC[4]}]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports {JC[4]}]
|
||||
##Sch name = JC8
|
||||
#set_property PACKAGE_PIN M19 [get_ports {JC[5]}]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports {JC[5]}]
|
||||
##Sch name = JC9
|
||||
#set_property PACKAGE_PIN P17 [get_ports {JC[6]}]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports {JC[6]}]
|
||||
##Sch name = JC10
|
||||
#set_property PACKAGE_PIN R18 [get_ports {JC[7]}]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports {JC[7]}]
|
||||
|
||||
|
||||
##Pmod Header JXADC
|
||||
##Sch name = XA1_P
|
||||
#set_property PACKAGE_PIN J3 [get_ports {JXADC[0]}]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[0]}]
|
||||
##Sch name = XA2_P
|
||||
#set_property PACKAGE_PIN L3 [get_ports {JXADC[1]}]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[1]}]
|
||||
##Sch name = XA3_P
|
||||
#set_property PACKAGE_PIN M2 [get_ports {JXADC[2]}]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[2]}]
|
||||
##Sch name = XA4_P
|
||||
#set_property PACKAGE_PIN N2 [get_ports {JXADC[3]}]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[3]}]
|
||||
##Sch name = XA1_N
|
||||
#set_property PACKAGE_PIN K3 [get_ports {JXADC[4]}]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[4]}]
|
||||
##Sch name = XA2_N
|
||||
#set_property PACKAGE_PIN M3 [get_ports {JXADC[5]}]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[5]}]
|
||||
##Sch name = XA3_N
|
||||
#set_property PACKAGE_PIN M1 [get_ports {JXADC[6]}]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[6]}]
|
||||
##Sch name = XA4_N
|
||||
#set_property PACKAGE_PIN N1 [get_ports {JXADC[7]}]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[7]}]
|
||||
|
||||
|
||||
|
||||
##VGA Connector
|
||||
set_property PACKAGE_PIN G19 [get_ports {io_rgb[8]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_rgb[8]}]
|
||||
set_property PACKAGE_PIN H19 [get_ports {io_rgb[9]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_rgb[9]}]
|
||||
set_property PACKAGE_PIN J19 [get_ports {io_rgb[10]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_rgb[10]}]
|
||||
set_property PACKAGE_PIN N19 [get_ports {io_rgb[11]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_rgb[11]}]
|
||||
set_property PACKAGE_PIN N18 [get_ports {io_rgb[0]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_rgb[0]}]
|
||||
set_property PACKAGE_PIN L18 [get_ports {io_rgb[1]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_rgb[1]}]
|
||||
set_property PACKAGE_PIN K18 [get_ports {io_rgb[2]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_rgb[2]}]
|
||||
set_property PACKAGE_PIN J18 [get_ports {io_rgb[3]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_rgb[3]}]
|
||||
set_property PACKAGE_PIN J17 [get_ports {io_rgb[4]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_rgb[4]}]
|
||||
set_property PACKAGE_PIN H17 [get_ports {io_rgb[5]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_rgb[5]}]
|
||||
set_property PACKAGE_PIN G17 [get_ports {io_rgb[6]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_rgb[6]}]
|
||||
set_property PACKAGE_PIN D17 [get_ports {io_rgb[7]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {io_rgb[7]}]
|
||||
set_property PACKAGE_PIN P19 [get_ports io_hsync]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports io_hsync]
|
||||
set_property PACKAGE_PIN R19 [get_ports io_vsync]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports io_vsync]
|
||||
|
||||
|
||||
##USB-RS232 Interface
|
||||
set_property PACKAGE_PIN B18 [get_ports io_rx]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports io_rx]
|
||||
set_property PACKAGE_PIN A18 [get_ports io_tx]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports io_tx]
|
||||
|
||||
|
||||
##USB HID (PS/2)
|
||||
#set_property PACKAGE_PIN C17 [get_ports PS2Clk]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports PS2Clk]
|
||||
#set_property PULLUP true [get_ports PS2Clk]
|
||||
#set_property PACKAGE_PIN B17 [get_ports PS2Data]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports PS2Data]
|
||||
#set_property PULLUP true [get_ports PS2Data]
|
||||
|
||||
|
||||
##Quad SPI Flash
|
||||
##Note that CCLK_0 cannot be placed in 7 series devices. You can access it using the
|
||||
##STARTUPE2 primitive.
|
||||
#set_property PACKAGE_PIN D18 [get_ports {QspiDB[0]}]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports {QspiDB[0]}]
|
||||
#set_property PACKAGE_PIN D19 [get_ports {QspiDB[1]}]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports {QspiDB[1]}]
|
||||
#set_property PACKAGE_PIN G18 [get_ports {QspiDB[2]}]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports {QspiDB[2]}]
|
||||
#set_property PACKAGE_PIN F18 [get_ports {QspiDB[3]}]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports {QspiDB[3]}]
|
||||
#set_property PACKAGE_PIN K19 [get_ports QspiCSn]
|
||||
#set_property IOSTANDARD LVCMOS33 [get_ports QspiCSn]
|
||||
|
||||
|
||||
## Configuration options, can be used for all designs
|
||||
set_property CONFIG_VOLTAGE 3.3 [current_design]
|
||||
set_property CFGBVS VCCO [current_design]
|
||||
17
lab1/vivado/basys3/generate_and_program.tcl
Normal file
17
lab1/vivado/basys3/generate_and_program.tcl
Normal file
@@ -0,0 +1,17 @@
|
||||
# Copyright 2021 Howard Lau
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# Only tested on Vivado 2020.1 on Windows 10
|
||||
source generate_bitstream.tcl
|
||||
source program_device.tcl
|
||||
55
lab1/vivado/basys3/generate_bitstream.tcl
Normal file
55
lab1/vivado/basys3/generate_bitstream.tcl
Normal file
@@ -0,0 +1,55 @@
|
||||
# Copyright 2021 Howard Lau
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
source open_project.tcl
|
||||
|
||||
while 1 {
|
||||
if { [catch {launch_runs synth_1 -jobs 4 } ] } {
|
||||
regexp {ERROR: \[Common (\d+-\d+)]} $errorInfo -> code
|
||||
if { [string equal $code "12-978"] } {
|
||||
puts "Already generated and up-to-date"
|
||||
break
|
||||
} elseif { [string equal $code "17-69"] } {
|
||||
puts "Out of date, reset runs"
|
||||
reset_runs synth_1
|
||||
continue
|
||||
} else {
|
||||
puts "UNKNOWN ERROR!!! $errorInfo"
|
||||
exit
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
wait_on_run synth_1
|
||||
|
||||
while 1 {
|
||||
if { [catch {launch_runs impl_1 -jobs 4 -to_step write_bitstream } ] } {
|
||||
regexp {ERROR: \[Vivado (\d+-\d+)]} $errorInfo -> code
|
||||
if { [string equal $code "12-978"] } {
|
||||
puts "Already generated and up-to-date"
|
||||
break
|
||||
} elseif { [string equal $code "12-1088"] } {
|
||||
puts "Out of date, reset runs"
|
||||
reset_runs impl_1
|
||||
continue
|
||||
} else {
|
||||
puts "UNKNOWN ERROR!!! $errorInfo"
|
||||
exit
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
wait_on_run impl_1
|
||||
39
lab1/vivado/basys3/open_project.tcl
Normal file
39
lab1/vivado/basys3/open_project.tcl
Normal file
@@ -0,0 +1,39 @@
|
||||
# Copyright 2021 Howard Lau
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# Only tested on Vivado 2020.1 on Windows 10
|
||||
|
||||
# set variables
|
||||
set project_dir riscv-basys3
|
||||
set project_name riscv-basys3
|
||||
set part xc7a35tcpg236-1
|
||||
set sources {../../verilog/basys3/Top.v}
|
||||
set test_sources {../../verilog/basys3/test.v}
|
||||
|
||||
# open the project. will create one if it doesn't exist
|
||||
if {[file exist $project_dir]} {
|
||||
# check that it's a directory
|
||||
if {! [file isdirectory $project_dir]} {
|
||||
puts "$project_dir exists, but it's a file"
|
||||
}
|
||||
open_project $project_dir/$project_name.xpr -part $part
|
||||
} else {
|
||||
create_project $project_name $project_dir -part $part
|
||||
}
|
||||
|
||||
add_files -norecurse $sources
|
||||
update_compile_order -fileset sources_1
|
||||
add_files -fileset constrs_1 -norecurse basys3.xdc
|
||||
add_files -fileset sim_1 -norecurse $test_sources
|
||||
update_compile_order -fileset sim_1
|
||||
24
lab1/vivado/basys3/program_device.tcl
Normal file
24
lab1/vivado/basys3/program_device.tcl
Normal file
@@ -0,0 +1,24 @@
|
||||
# Copyright 2021 Howard Lau
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# Only tested on Vivado 2020.1 on Windows 10
|
||||
open_hw_manager
|
||||
connect_hw_server -allow_non_jtag
|
||||
open_hw_target
|
||||
current_hw_device [get_hw_devices xc7a35t_0]
|
||||
refresh_hw_server [current_hw_server]
|
||||
open_hw_target [lindex [get_hw_targets] 0]
|
||||
set_property PROGRAM.FILE {./riscv-basys3/riscv-basys3.runs/impl_1/Top.bit} [get_hw_devices xc7a35t_0]
|
||||
program_hw_devices [get_hw_devices xc7a35t_0]
|
||||
close_hw_target
|
||||
4
lab1/vivado/basys3/run.ps1
Normal file
4
lab1/vivado/basys3/run.ps1
Normal file
@@ -0,0 +1,4 @@
|
||||
cd ..
|
||||
sbt run
|
||||
cd vivado
|
||||
C:\Xilinx\Vivado\2020.1\bin\vivado -mode batch -source .\generate_and_program.tcl
|
||||
24
lab1/vivado/basys3/run_simulation.tcl
Normal file
24
lab1/vivado/basys3/run_simulation.tcl
Normal file
@@ -0,0 +1,24 @@
|
||||
# Copyright 2021 Howard Lau
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
source open_project.tcl
|
||||
|
||||
launch_simulation
|
||||
restart
|
||||
open_vcd
|
||||
log_wave -recursive [get_object /test/top/cpu/*]
|
||||
log_vcd [get_object /test/top/cpu/*]
|
||||
run 1000ns
|
||||
close_vcd
|
||||
close_sim
|
||||
17
lab1/vivado/pynq/generate_and_program.tcl
Normal file
17
lab1/vivado/pynq/generate_and_program.tcl
Normal file
@@ -0,0 +1,17 @@
|
||||
# Copyright 2021 Howard Lau
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# Only tested on Vivado 2020.1 on Windows 10
|
||||
source generate_bitstream.tcl
|
||||
source program_device.tcl
|
||||
56
lab1/vivado/pynq/generate_bitstream.tcl
Normal file
56
lab1/vivado/pynq/generate_bitstream.tcl
Normal file
@@ -0,0 +1,56 @@
|
||||
# Copyright 2021 Howard Lau
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
source open_project.tcl
|
||||
set_param general.maxThreads 16
|
||||
|
||||
while 1 {
|
||||
if { [catch {launch_runs synth_1 -jobs 16 } ] } {
|
||||
regexp {ERROR: \[Common (\d+-\d+)]} $errorInfo -> code
|
||||
if { [string equal $code "12-978"] } {
|
||||
puts "Already generated and up-to-date"
|
||||
break
|
||||
} elseif { [string equal $code "17-69"] } {
|
||||
puts "Out of date, reset runs"
|
||||
reset_runs synth_1
|
||||
continue
|
||||
} else {
|
||||
puts "UNKNOWN ERROR!!! $errorInfo"
|
||||
exit
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
wait_on_run synth_1
|
||||
|
||||
while 1 {
|
||||
if { [catch {launch_runs impl_1 -jobs 16 -to_step write_bitstream } ] } {
|
||||
regexp {ERROR: \[Vivado (\d+-\d+)]} $errorInfo -> code
|
||||
if { [string equal $code "12-978"] } {
|
||||
puts "Already generated and up-to-date"
|
||||
break
|
||||
} elseif { [string equal $code "12-1088"] } {
|
||||
puts "Out of date, reset runs"
|
||||
reset_runs impl_1
|
||||
continue
|
||||
} else {
|
||||
puts "UNKNOWN ERROR!!! $errorInfo"
|
||||
exit
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
wait_on_run impl_1
|
||||
40
lab1/vivado/pynq/open_project.tcl
Normal file
40
lab1/vivado/pynq/open_project.tcl
Normal file
@@ -0,0 +1,40 @@
|
||||
# Copyright 2021 Howard Lau
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# Only tested on Vivado 2020.1 on Windows 10
|
||||
|
||||
# set variables
|
||||
set project_dir riscv-pynq
|
||||
set project_name riscv-pynq
|
||||
set part xc7z020clg400-1
|
||||
set sources {../../verilog/pynq/Top.v}
|
||||
set test_sources {../../verilog/pynq/test.v}
|
||||
|
||||
# open the project. will create one if it doesn't exist
|
||||
if {[file exist $project_dir]} {
|
||||
# check that it's a directory
|
||||
if {! [file isdirectory $project_dir]} {
|
||||
puts "$project_dir exists, but it's a file"
|
||||
}
|
||||
open_project $project_dir/$project_name.xpr -part $part
|
||||
} else {
|
||||
create_project $project_name $project_dir -part $part
|
||||
}
|
||||
|
||||
add_files -norecurse $sources
|
||||
add_files -norecurse ../../verilog/pynq/TMDS_PLLVR.v
|
||||
update_compile_order -fileset sources_1
|
||||
add_files -fileset constrs_1 -norecurse pynq.xdc
|
||||
add_files -fileset sim_1 -norecurse $test_sources
|
||||
update_compile_order -fileset sim_1
|
||||
22
lab1/vivado/pynq/program_device.tcl
Normal file
22
lab1/vivado/pynq/program_device.tcl
Normal file
@@ -0,0 +1,22 @@
|
||||
# Copyright 2021 Howard Lau
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# Only tested on Vivado 2020.1 on Windows 10
|
||||
open_hw_manager
|
||||
connect_hw_server -allow_non_jtag
|
||||
refresh_hw_server [current_hw_server]
|
||||
open_hw_target [lindex [get_hw_targets] 0]
|
||||
set_property PROGRAM.FILE {riscv-pynq/riscv-pynq.runs/impl_1/Top.bit} [get_hw_devices xc7z020_1]
|
||||
program_hw_devices [get_hw_devices xc7z020_1]
|
||||
close_hw_target
|
||||
189
lab1/vivado/pynq/pynq.xdc
Normal file
189
lab1/vivado/pynq/pynq.xdc
Normal file
@@ -0,0 +1,189 @@
|
||||
## This file is a general .xdc for the PYNQ-Z1 board Rev. C
|
||||
## To use it in a project:
|
||||
## - uncomment the lines corresponding to used pins
|
||||
## - rename the used ports (in each line, after get_ports) according to the top level signal names in the project
|
||||
|
||||
## Clock signal 125 MHz
|
||||
|
||||
set_property -dict { PACKAGE_PIN H16 IOSTANDARD LVCMOS33 } [get_ports { clock }]; #IO_L13P_T2_MRCC_35 Sch=sysclk
|
||||
create_clock -add -name sys_clk_pin -period 8.00 -waveform {0 4} [get_ports { clock }];
|
||||
|
||||
##Switches
|
||||
|
||||
set_property -dict { PACKAGE_PIN M20 IOSTANDARD LVCMOS33 } [get_ports { io_debug_step }]; #IO_L7N_T1_AD2N_35 Sch=sw[0]
|
||||
#set_property -dict { PACKAGE_PIN M19 IOSTANDARD LVCMOS33 } [get_ports { sw[1] }]; #IO_L7P_T1_AD2P_35 Sch=sw[1]
|
||||
|
||||
##RGB LEDs
|
||||
|
||||
#set_property -dict { PACKAGE_PIN L15 IOSTANDARD LVCMOS33 } [get_ports { led4_b }]; #IO_L22N_T3_AD7N_35 Sch=led4_b
|
||||
#set_property -dict { PACKAGE_PIN G17 IOSTANDARD LVCMOS33 } [get_ports { led4_g }]; #IO_L16P_T2_35 Sch=led4_g
|
||||
#set_property -dict { PACKAGE_PIN N15 IOSTANDARD LVCMOS33 } [get_ports { led4_r }]; #IO_L21P_T3_DQS_AD14P_35 Sch=led4_r
|
||||
#set_property -dict { PACKAGE_PIN G14 IOSTANDARD LVCMOS33 } [get_ports { led5_b }]; #IO_0_35 Sch=led5_b
|
||||
#set_property -dict { PACKAGE_PIN L14 IOSTANDARD LVCMOS33 } [get_ports { led5_g }]; #IO_L22P_T3_AD7P_35 Sch=led5_g
|
||||
#set_property -dict { PACKAGE_PIN M15 IOSTANDARD LVCMOS33 } [get_ports { led5_r }]; #IO_L23N_T3_35 Sch=led5_r
|
||||
|
||||
##LEDs
|
||||
|
||||
set_property -dict { PACKAGE_PIN R14 IOSTANDARD LVCMOS33 } [get_ports { io_led[0] }]; #IO_L6N_T0_VREF_34 Sch=led[0]
|
||||
set_property -dict { PACKAGE_PIN P14 IOSTANDARD LVCMOS33 } [get_ports { io_led[1] }]; #IO_L6P_T0_34 Sch=led[1]
|
||||
set_property -dict { PACKAGE_PIN N16 IOSTANDARD LVCMOS33 } [get_ports { io_led[2] }]; #IO_L21N_T3_DQS_AD14N_35 Sch=led[2]
|
||||
set_property -dict { PACKAGE_PIN M14 IOSTANDARD LVCMOS33 } [get_ports { io_led[3] }]; #IO_L23P_T3_35 Sch=led[3]
|
||||
|
||||
##Buttons
|
||||
|
||||
set_property -dict { PACKAGE_PIN D19 IOSTANDARD LVCMOS33 } [get_ports { reset }]; #IO_L4P_T0_35 Sch=btn[0]
|
||||
set_property -dict { PACKAGE_PIN D20 IOSTANDARD LVCMOS33 } [get_ports { io_debug_clk }]; #IO_L4N_T0_35 Sch=btn[1]
|
||||
#set_property -dict { PACKAGE_PIN L20 IOSTANDARD LVCMOS33 } [get_ports { btn[2] }]; #IO_L9N_T1_DQS_AD3N_35 Sch=btn[2]
|
||||
#set_property -dict { PACKAGE_PIN L19 IOSTANDARD LVCMOS33 } [get_ports { btn[3] }]; #IO_L9P_T1_DQS_AD3P_35 Sch=btn[3]
|
||||
|
||||
##Pmod Header JA
|
||||
|
||||
#set_property -dict { PACKAGE_PIN Y18 IOSTANDARD LVCMOS33 } [get_ports { io_rx }]; #IO_L17P_T2_34 Sch=ja_p[1]
|
||||
#set_property -dict { PACKAGE_PIN Y19 IOSTANDARD LVCMOS33 } [get_ports { io_tx }]; #IO_L17N_T2_34 Sch=ja_n[1]
|
||||
set_property -dict { PACKAGE_PIN Y16 IOSTANDARD LVCMOS33 } [get_ports { io_rx }]; #IO_L7P_T1_34 Sch=ja_p[2]
|
||||
set_property -dict { PACKAGE_PIN Y17 IOSTANDARD LVCMOS33 } [get_ports { io_tx }]; #IO_L7N_T1_34 Sch=ja_n[2]
|
||||
#set_property -dict { PACKAGE_PIN U18 IOSTANDARD LVCMOS33 } [get_ports { ja[4] }]; #IO_L12P_T1_MRCC_34 Sch=ja_p[3]
|
||||
#set_property -dict { PACKAGE_PIN U19 IOSTANDARD LVCMOS33 } [get_ports { ja[5] }]; #IO_L12N_T1_MRCC_34 Sch=ja_n[3]
|
||||
#set_property -dict { PACKAGE_PIN W18 IOSTANDARD LVCMOS33 } [get_ports { ja[6] }]; #IO_L22P_T3_34 Sch=ja_p[4]
|
||||
#set_property -dict { PACKAGE_PIN W19 IOSTANDARD LVCMOS33 } [get_ports { ja[7] }]; #IO_L22N_T3_34 Sch=ja_n[4]
|
||||
|
||||
##Pmod Header JB
|
||||
|
||||
#set_property -dict { PACKAGE_PIN W14 IOSTANDARD LVCMOS33 } [get_ports { jb[0] }]; #IO_L8P_T1_34 Sch=jb_p[1]
|
||||
#set_property -dict { PACKAGE_PIN Y14 IOSTANDARD LVCMOS33 } [get_ports { jb[1] }]; #IO_L8N_T1_34 Sch=jb_n[1]
|
||||
#set_property -dict { PACKAGE_PIN T11 IOSTANDARD LVCMOS33 } [get_ports { jb[2] }]; #IO_L1P_T0_34 Sch=jb_p[2]
|
||||
#set_property -dict { PACKAGE_PIN T10 IOSTANDARD LVCMOS33 } [get_ports { jb[3] }]; #IO_L1N_T0_34 Sch=jb_n[2]
|
||||
#set_property -dict { PACKAGE_PIN V16 IOSTANDARD LVCMOS33 } [get_ports { jb[4] }]; #IO_L18P_T2_34 Sch=jb_p[3]
|
||||
#set_property -dict { PACKAGE_PIN W16 IOSTANDARD LVCMOS33 } [get_ports { jb[5] }]; #IO_L18N_T2_34 Sch=jb_n[3]
|
||||
#set_property -dict { PACKAGE_PIN V12 IOSTANDARD LVCMOS33 } [get_ports { jb[6] }]; #IO_L4P_T0_34 Sch=jb_p[4]
|
||||
#set_property -dict { PACKAGE_PIN W13 IOSTANDARD LVCMOS33 } [get_ports { jb[7] }]; #IO_L4N_T0_34 Sch=jb_n[4]
|
||||
|
||||
##Audio Out
|
||||
|
||||
#set_property -dict { PACKAGE_PIN R18 IOSTANDARD LVCMOS33 } [get_ports { aud_pwm }]; #IO_L20N_T3_34 Sch=aud_pwm
|
||||
#set_property -dict { PACKAGE_PIN T17 IOSTANDARD LVCMOS33 } [get_ports { aud_sd }]; #IO_L20P_T3_34 Sch=aud_sd
|
||||
|
||||
##Mic input
|
||||
|
||||
#set_property -dict { PACKAGE_PIN F17 IOSTANDARD LVCMOS33 } [get_ports { m_clk }]; #IO_L6N_T0_VREF_35 Sch=m_clk
|
||||
#set_property -dict { PACKAGE_PIN G18 IOSTANDARD LVCMOS33 } [get_ports { m_data }]; #IO_L16N_T2_35 Sch=m_data
|
||||
|
||||
##ChipKit Single Ended Analog Inputs
|
||||
##NOTE: The ck_an_p pins can be used as single ended analog inputs with voltages from 0-3.3V (Chipkit Analog pins A0-A5).
|
||||
## These signals should only be connected to the XADC core. When using these pins as digital I/O, use pins ck_io[14-19].
|
||||
|
||||
#set_property -dict { PACKAGE_PIN D18 IOSTANDARD LVCMOS33 } [get_ports { ck_an_n[0] }]; #IO_L3N_T0_DQS_AD1N_35 Sch=ck_an_n[0]
|
||||
#set_property -dict { PACKAGE_PIN E17 IOSTANDARD LVCMOS33 } [get_ports { ck_an_p[0] }]; #IO_L3P_T0_DQS_AD1P_35 Sch=ck_an_p[0]
|
||||
#set_property -dict { PACKAGE_PIN E19 IOSTANDARD LVCMOS33 } [get_ports { ck_an_n[1] }]; #IO_L5N_T0_AD9N_35 Sch=ck_an_n[1]
|
||||
#set_property -dict { PACKAGE_PIN E18 IOSTANDARD LVCMOS33 } [get_ports { ck_an_p[1] }]; #IO_L5P_T0_AD9P_35 Sch=ck_an_p[1]
|
||||
#set_property -dict { PACKAGE_PIN J14 IOSTANDARD LVCMOS33 } [get_ports { ck_an_n[2] }]; #IO_L20N_T3_AD6N_35 Sch=ck_an_n[2]
|
||||
#set_property -dict { PACKAGE_PIN K14 IOSTANDARD LVCMOS33 } [get_ports { ck_an_p[2] }]; #IO_L20P_T3_AD6P_35 Sch=ck_an_p[2]
|
||||
#set_property -dict { PACKAGE_PIN J16 IOSTANDARD LVCMOS33 } [get_ports { ck_an_n[3] }]; #IO_L24N_T3_AD15N_35 Sch=ck_an_n[3]
|
||||
#set_property -dict { PACKAGE_PIN K16 IOSTANDARD LVCMOS33 } [get_ports { ck_an_p[3] }]; #IO_L24P_T3_AD15P_35 Sch=ck_an_p[3]
|
||||
#set_property -dict { PACKAGE_PIN H20 IOSTANDARD LVCMOS33 } [get_ports { ck_an_n[4] }]; #IO_L17N_T2_AD5N_35 Sch=ck_an_n[4]
|
||||
#set_property -dict { PACKAGE_PIN J20 IOSTANDARD LVCMOS33 } [get_ports { ck_an_p[4] }]; #IO_L17P_T2_AD5P_35 Sch=ck_an_p[4]
|
||||
#set_property -dict { PACKAGE_PIN G20 IOSTANDARD LVCMOS33 } [get_ports { ck_an_n[5] }]; #IO_L18N_T2_AD13N_35 Sch=ck_an_n[5]
|
||||
#set_property -dict { PACKAGE_PIN G19 IOSTANDARD LVCMOS33 } [get_ports { ck_an_p[5] }]; #IO_L18P_T2_AD13P_35 Sch=ck_an_p[5]
|
||||
|
||||
##ChipKit Digital I/O Low
|
||||
|
||||
#set_property -dict { PACKAGE_PIN T14 IOSTANDARD LVCMOS33 } [get_ports { ck_io[0] }]; #IO_L5P_T0_34 Sch=ck_io[0]
|
||||
#set_property -dict { PACKAGE_PIN U12 IOSTANDARD LVCMOS33 } [get_ports { ck_io[1] }]; #IO_L2N_T0_34 Sch=ck_io[1]
|
||||
#set_property -dict { PACKAGE_PIN U13 IOSTANDARD LVCMOS33 } [get_ports { ck_io[2] }]; #IO_L3P_T0_DQS_PUDC_B_34 Sch=ck_io[2]
|
||||
#set_property -dict { PACKAGE_PIN V13 IOSTANDARD LVCMOS33 } [get_ports { ck_io[3] }]; #IO_L3N_T0_DQS_34 Sch=ck_io[3]
|
||||
#set_property -dict { PACKAGE_PIN V15 IOSTANDARD LVCMOS33 } [get_ports { ck_io[4] }]; #IO_L10P_T1_34 Sch=ck_io[4]
|
||||
#set_property -dict { PACKAGE_PIN T15 IOSTANDARD LVCMOS33 } [get_ports { ck_io[5] }]; #IO_L5N_T0_34 Sch=ck_io[5]
|
||||
#set_property -dict { PACKAGE_PIN R16 IOSTANDARD LVCMOS33 } [get_ports { ck_io[6] }]; #IO_L19P_T3_34 Sch=ck_io[6]
|
||||
#set_property -dict { PACKAGE_PIN U17 IOSTANDARD LVCMOS33 } [get_ports { ck_io[7] }]; #IO_L9N_T1_DQS_34 Sch=ck_io[7]
|
||||
#set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 } [get_ports { ck_io[8] }]; #IO_L21P_T3_DQS_34 Sch=ck_io[8]
|
||||
#set_property -dict { PACKAGE_PIN V18 IOSTANDARD LVCMOS33 } [get_ports { ck_io[9] }]; #IO_L21N_T3_DQS_34 Sch=ck_io[9]
|
||||
#set_property -dict { PACKAGE_PIN T16 IOSTANDARD LVCMOS33 } [get_ports { ck_io[10] }]; #IO_L9P_T1_DQS_34 Sch=ck_io[10]
|
||||
#set_property -dict { PACKAGE_PIN R17 IOSTANDARD LVCMOS33 } [get_ports { ck_io[11] }]; #IO_L19N_T3_VREF_34 Sch=ck_io[11]
|
||||
#set_property -dict { PACKAGE_PIN P18 IOSTANDARD LVCMOS33 } [get_ports { ck_io[12] }]; #IO_L23N_T3_34 Sch=ck_io[12]
|
||||
#set_property -dict { PACKAGE_PIN N17 IOSTANDARD LVCMOS33 } [get_ports { ck_io[13] }]; #IO_L23P_T3_34 Sch=ck_io[13]
|
||||
|
||||
##ChipKit Digital I/O On Outer Analog Header
|
||||
##NOTE: These pins should be used when using the analog header signals A0-A5 as digital I/O (Chipkit digital pins 14-19)
|
||||
|
||||
#set_property -dict { PACKAGE_PIN Y11 IOSTANDARD LVCMOS33 } [get_ports { ck_io[14] }]; #IO_L18N_T2_13 Sch=ck_a[0]
|
||||
#set_property -dict { PACKAGE_PIN Y12 IOSTANDARD LVCMOS33 } [get_ports { ck_io[15] }]; #IO_L20P_T3_13 Sch=ck_a[1]
|
||||
#set_property -dict { PACKAGE_PIN W11 IOSTANDARD LVCMOS33 } [get_ports { ck_io[16] }]; #IO_L18P_T2_13 Sch=ck_a[2]
|
||||
#set_property -dict { PACKAGE_PIN V11 IOSTANDARD LVCMOS33 } [get_ports { ck_io[17] }]; #IO_L21P_T3_DQS_13 Sch=ck_a[3]
|
||||
#set_property -dict { PACKAGE_PIN T5 IOSTANDARD LVCMOS33 } [get_ports { ck_io[18] }]; #IO_L19P_T3_13 Sch=ck_a[4]
|
||||
#set_property -dict { PACKAGE_PIN U10 IOSTANDARD LVCMOS33 } [get_ports { ck_io[19] }]; #IO_L12N_T1_MRCC_13 Sch=ck_a[5]
|
||||
|
||||
##ChipKit Digital I/O On Inner Analog Header
|
||||
##NOTE: These pins will need to be connected to the XADC core when used as differential analog inputs (Chipkit analog pins A6-A11)
|
||||
|
||||
#set_property -dict { PACKAGE_PIN B20 IOSTANDARD LVCMOS33 } [get_ports { ck_io[20] }]; #IO_L1N_T0_AD0N_35 Sch=ad_n[0]
|
||||
#set_property -dict { PACKAGE_PIN C20 IOSTANDARD LVCMOS33 } [get_ports { ck_io[21] }]; #IO_L1P_T0_AD0P_35 Sch=ad_p[0]
|
||||
#set_property -dict { PACKAGE_PIN F20 IOSTANDARD LVCMOS33 } [get_ports { ck_io[22] }]; #IO_L15N_T2_DQS_AD12N_35 Sch=ad_n[12]
|
||||
#set_property -dict { PACKAGE_PIN F19 IOSTANDARD LVCMOS33 } [get_ports { ck_io[23] }]; #IO_L15P_T2_DQS_AD12P_35 Sch=ad_p[12]
|
||||
#set_property -dict { PACKAGE_PIN A20 IOSTANDARD LVCMOS33 } [get_ports { ck_io[24] }]; #IO_L2N_T0_AD8N_35 Sch=ad_n[8]
|
||||
#set_property -dict { PACKAGE_PIN B19 IOSTANDARD LVCMOS33 } [get_ports { ck_io[25] }]; #IO_L2P_T0_AD8P_35 Sch=ad_p[8]
|
||||
|
||||
##ChipKit Digital I/O High
|
||||
|
||||
#set_property -dict { PACKAGE_PIN U5 IOSTANDARD LVCMOS33 } [get_ports { ck_io[26] }]; #IO_L19N_T3_VREF_13 Sch=ck_io[26]
|
||||
#set_property -dict { PACKAGE_PIN V5 IOSTANDARD LVCMOS33 } [get_ports { ck_io[27] }]; #IO_L6N_T0_VREF_13 Sch=ck_io[27]
|
||||
#set_property -dict { PACKAGE_PIN V6 IOSTANDARD LVCMOS33 } [get_ports { ck_io[28] }]; #IO_L22P_T3_13 Sch=ck_io[28]
|
||||
#set_property -dict { PACKAGE_PIN U7 IOSTANDARD LVCMOS33 } [get_ports { ck_io[29] }]; #IO_L11P_T1_SRCC_13 Sch=ck_io[29]
|
||||
#set_property -dict { PACKAGE_PIN V7 IOSTANDARD LVCMOS33 } [get_ports { ck_io[30] }]; #IO_L11N_T1_SRCC_13 Sch=ck_io[30]
|
||||
#set_property -dict { PACKAGE_PIN U8 IOSTANDARD LVCMOS33 } [get_ports { ck_io[31] }]; #IO_L17N_T2_13 Sch=ck_io[31]
|
||||
#set_property -dict { PACKAGE_PIN V8 IOSTANDARD LVCMOS33 } [get_ports { ck_io[32] }]; #IO_L15P_T2_DQS_13 Sch=ck_io[32]
|
||||
#set_property -dict { PACKAGE_PIN V10 IOSTANDARD LVCMOS33 } [get_ports { ck_io[33] }]; #IO_L21N_T3_DQS_13 Sch=ck_io[33]
|
||||
#set_property -dict { PACKAGE_PIN W10 IOSTANDARD LVCMOS33 } [get_ports { ck_io[34] }]; #IO_L16P_T2_13 Sch=ck_io[34]
|
||||
#set_property -dict { PACKAGE_PIN W6 IOSTANDARD LVCMOS33 } [get_ports { ck_io[35] }]; #IO_L22N_T3_13 Sch=ck_io[35]
|
||||
#set_property -dict { PACKAGE_PIN Y6 IOSTANDARD LVCMOS33 } [get_ports { ck_io[36] }]; #IO_L13N_T2_MRCC_13 Sch=ck_io[36]
|
||||
#set_property -dict { PACKAGE_PIN Y7 IOSTANDARD LVCMOS33 } [get_ports { ck_io[37] }]; #IO_L13P_T2_MRCC_13 Sch=ck_io[37]
|
||||
#set_property -dict { PACKAGE_PIN W8 IOSTANDARD LVCMOS33 } [get_ports { ck_io[38] }]; #IO_L15N_T2_DQS_13 Sch=ck_io[38]
|
||||
#set_property -dict { PACKAGE_PIN Y8 IOSTANDARD LVCMOS33 } [get_ports { ck_io[39] }]; #IO_L14N_T2_SRCC_13 Sch=ck_io[39]
|
||||
#set_property -dict { PACKAGE_PIN W9 IOSTANDARD LVCMOS33 } [get_ports { ck_io[40] }]; #IO_L16N_T2_13 Sch=ck_io[40]
|
||||
#set_property -dict { PACKAGE_PIN Y9 IOSTANDARD LVCMOS33 } [get_ports { ck_io[41] }]; #IO_L14P_T2_SRCC_13 Sch=ck_io[41]
|
||||
#set_property -dict { PACKAGE_PIN Y13 IOSTANDARD LVCMOS33 } [get_ports { ck_io[42] }]; #IO_L20N_T3_13 Sch=ck_ioa
|
||||
|
||||
## ChipKit SPI
|
||||
|
||||
#set_property -dict { PACKAGE_PIN W15 IOSTANDARD LVCMOS33 } [get_ports { ck_miso }]; #IO_L10N_T1_34 Sch=ck_miso
|
||||
#set_property -dict { PACKAGE_PIN T12 IOSTANDARD LVCMOS33 } [get_ports { ck_mosi }]; #IO_L2P_T0_34 Sch=ck_mosi
|
||||
#set_property -dict { PACKAGE_PIN H15 IOSTANDARD LVCMOS33 } [get_ports { ck_sck }]; #IO_L19P_T3_35 Sch=ck_sck
|
||||
#set_property -dict { PACKAGE_PIN F16 IOSTANDARD LVCMOS33 } [get_ports { ck_ss }]; #IO_L6P_T0_35 Sch=ck_ss
|
||||
|
||||
## ChipKit I2C
|
||||
|
||||
#set_property -dict { PACKAGE_PIN P16 IOSTANDARD LVCMOS33 } [get_ports { ck_scl }]; #IO_L24N_T3_34 Sch=ck_scl
|
||||
#set_property -dict { PACKAGE_PIN P15 IOSTANDARD LVCMOS33 } [get_ports { ck_sda }]; #IO_L24P_T3_34 Sch=ck_sda
|
||||
|
||||
##HDMI Rx
|
||||
|
||||
#set_property -dict { PACKAGE_PIN H17 IOSTANDARD LVCMOS33 } [get_ports { hdmi_rx_cec }]; #IO_L13N_T2_MRCC_35 Sch=hdmi_rx_cec
|
||||
set_property -dict { PACKAGE_PIN P19 IOSTANDARD TMDS_33 } [get_ports { io_debug_hdmi_clk_n }]; #IO_L13N_T2_MRCC_34 Sch=hdmi_rx_clk_n
|
||||
set_property -dict { PACKAGE_PIN N18 IOSTANDARD TMDS_33 } [get_ports { io_debug_hdmi_clk_p }]; #IO_L13P_T2_MRCC_34 Sch=hdmi_rx_clk_p
|
||||
set_property -dict { PACKAGE_PIN W20 IOSTANDARD TMDS_33 } [get_ports { io_debug_hdmi_data_n[0] }]; #IO_L16N_T2_34 Sch=hdmi_rx_d_n[0]
|
||||
set_property -dict { PACKAGE_PIN V20 IOSTANDARD TMDS_33 } [get_ports { io_debug_hdmi_data_p[0] }]; #IO_L16P_T2_34 Sch=hdmi_rx_d_p[0]
|
||||
set_property -dict { PACKAGE_PIN U20 IOSTANDARD TMDS_33 } [get_ports { io_debug_hdmi_data_n[1] }]; #IO_L15N_T2_DQS_34 Sch=hdmi_rx_d_n[1]
|
||||
set_property -dict { PACKAGE_PIN T20 IOSTANDARD TMDS_33 } [get_ports { io_debug_hdmi_data_p[1] }]; #IO_L15P_T2_DQS_34 Sch=hdmi_rx_d_p[1]
|
||||
set_property -dict { PACKAGE_PIN P20 IOSTANDARD TMDS_33 } [get_ports { io_debug_hdmi_data_n[2] }]; #IO_L14N_T2_SRCC_34 Sch=hdmi_rx_d_n[2]
|
||||
set_property -dict { PACKAGE_PIN N20 IOSTANDARD TMDS_33 } [get_ports { io_debug_hdmi_data_p[2] }]; #IO_L14P_T2_SRCC_34 Sch=hdmi_rx_d_p[2]
|
||||
set_property -dict { PACKAGE_PIN T19 IOSTANDARD LVCMOS33 } [get_ports { io_debug_hdmi_hpdn }]; #IO_25_34 Sch=hdmi_rx_hpd
|
||||
#set_property -dict { PACKAGE_PIN U14 IOSTANDARD LVCMOS33 } [get_ports { hdmi_rx_scl }]; #IO_L11P_T1_SRCC_34 Sch=hdmi_rx_scl
|
||||
#set_property -dict { PACKAGE_PIN U15 IOSTANDARD LVCMOS33 } [get_ports { hdmi_rx_sda }]; #IO_L11N_T1_SRCC_34 Sch=hdmi_rx_sda
|
||||
|
||||
##HDMI Tx
|
||||
|
||||
#set_property -dict { PACKAGE_PIN G15 IOSTANDARD LVCMOS33 } [get_ports { hdmi_tx_cec }]; #IO_L19N_T3_VREF_35 Sch=hdmi_tx_cec
|
||||
set_property -dict { PACKAGE_PIN L17 IOSTANDARD TMDS_33 } [get_ports { io_hdmi_clk_n }]; #IO_L11N_T1_SRCC_35 Sch=hdmi_tx_clk_n
|
||||
set_property -dict { PACKAGE_PIN L16 IOSTANDARD TMDS_33 } [get_ports { io_hdmi_clk_p }]; #IO_L11P_T1_SRCC_35 Sch=hdmi_tx_clk_p
|
||||
set_property -dict { PACKAGE_PIN K18 IOSTANDARD TMDS_33 } [get_ports { io_hdmi_data_n[0] }]; #IO_L12N_T1_MRCC_35 Sch=hdmi_tx_d_n[0]
|
||||
set_property -dict { PACKAGE_PIN K17 IOSTANDARD TMDS_33 } [get_ports { io_hdmi_data_p[0] }]; #IO_L12P_T1_MRCC_35 Sch=hdmi_tx_d_p[0]
|
||||
set_property -dict { PACKAGE_PIN J19 IOSTANDARD TMDS_33 } [get_ports { io_hdmi_data_n[1] }]; #IO_L10N_T1_AD11N_35 Sch=hdmi_tx_d_n[1]
|
||||
set_property -dict { PACKAGE_PIN K19 IOSTANDARD TMDS_33 } [get_ports { io_hdmi_data_p[1] }]; #IO_L10P_T1_AD11P_35 Sch=hdmi_tx_d_p[1]
|
||||
set_property -dict { PACKAGE_PIN H18 IOSTANDARD TMDS_33 } [get_ports { io_hdmi_data_n[2] }]; #IO_L14N_T2_AD4N_SRCC_35 Sch=hdmi_tx_d_n[2]
|
||||
set_property -dict { PACKAGE_PIN J18 IOSTANDARD TMDS_33 } [get_ports { io_hdmi_data_p[2] }]; #IO_L14P_T2_AD4P_SRCC_35 Sch=hdmi_tx_d_p[2]
|
||||
set_property -dict { PACKAGE_PIN R19 IOSTANDARD LVCMOS33 } [get_ports { io_hdmi_hpdn }]; #IO_0_34 Sch=hdmi_tx_hpdn
|
||||
#set_property -dict { PACKAGE_PIN M17 IOSTANDARD LVCMOS33 } [get_ports { hdmi_tx_scl }]; #IO_L8P_T1_AD10P_35 Sch=hdmi_tx_scl
|
||||
#set_property -dict { PACKAGE_PIN M18 IOSTANDARD LVCMOS33 } [get_ports { hdmi_tx_sda }]; #IO_L8N_T1_AD10N_35 Sch=hdmi_tx_sda
|
||||
|
||||
##Crypto SDA
|
||||
|
||||
#set_property -dict { PACKAGE_PIN J15 IOSTANDARD LVCMOS33 } [get_ports { crypto_sda }]; #IO_25_35 Sch=crypto_sda
|
||||
4
lab1/vivado/pynq/run.ps1
Normal file
4
lab1/vivado/pynq/run.ps1
Normal file
@@ -0,0 +1,4 @@
|
||||
cd ..
|
||||
sbt run
|
||||
cd vivado
|
||||
C:\Xilinx\Vivado\2020.1\bin\vivado -mode batch -source .\generate_and_program.tcl
|
||||
28
lab1/vivado/pynq/run_simulation.tcl
Normal file
28
lab1/vivado/pynq/run_simulation.tcl
Normal file
@@ -0,0 +1,28 @@
|
||||
# Copyright 2021 Howard Lau
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
source open_project.tcl
|
||||
|
||||
launch_simulation
|
||||
restart
|
||||
open_vcd
|
||||
#log_wave -recursive [get_object /test/top/hdmi_display/*]
|
||||
#log_vcd [get_object /test/top/hdmi_display/*]
|
||||
#log_wave -recursive [get_object /test/top/*]
|
||||
#log_vcd [get_object /test/top/*]
|
||||
log_wave -recursive [get_object /test/top/hdmi_display/serdesBlue/osr10/*]
|
||||
log_vcd [get_object /test/top/hdmi_display/serdesBlue/osr10/*]
|
||||
run 1000000ns
|
||||
close_vcd
|
||||
close_sim
|
||||
358
lab2/.gitignore
vendored
Normal file
358
lab2/.gitignore
vendored
Normal file
@@ -0,0 +1,358 @@
|
||||
### Project Specific stuff
|
||||
test_run_dir/*
|
||||
### XilinxISE template
|
||||
# intermediate build files
|
||||
*.bgn
|
||||
*.bit
|
||||
*.bld
|
||||
*.cmd_log
|
||||
*.drc
|
||||
*.ll
|
||||
*.lso
|
||||
*.msd
|
||||
*.msk
|
||||
*.ncd
|
||||
*.ngc
|
||||
*.ngd
|
||||
*.ngr
|
||||
*.pad
|
||||
*.par
|
||||
*.pcf
|
||||
*.prj
|
||||
*.ptwx
|
||||
*.rbb
|
||||
*.rbd
|
||||
*.stx
|
||||
*.syr
|
||||
*.twr
|
||||
*.twx
|
||||
*.unroutes
|
||||
*.ut
|
||||
*.xpi
|
||||
*.xst
|
||||
*_bitgen.xwbt
|
||||
*_envsettings.html
|
||||
*_map.map
|
||||
*_map.mrp
|
||||
*_map.ngm
|
||||
*_map.xrpt
|
||||
*_ngdbuild.xrpt
|
||||
*_pad.csv
|
||||
*_pad.txt
|
||||
*_par.xrpt
|
||||
*_summary.html
|
||||
*_summary.xml
|
||||
*_usage.xml
|
||||
*_xst.xrpt
|
||||
|
||||
# project-wide generated files
|
||||
*.gise
|
||||
par_usage_statistics.html
|
||||
usage_statistics_webtalk.html
|
||||
webtalk.log
|
||||
webtalk_pn.xml
|
||||
|
||||
# generated folders
|
||||
iseconfig/
|
||||
xlnx_auto_0_xdb/
|
||||
xst/
|
||||
_ngo/
|
||||
_xmsgs/
|
||||
### Eclipse template
|
||||
*.pydevproject
|
||||
.metadata
|
||||
.gradle
|
||||
bin/
|
||||
tmp/
|
||||
*.tmp
|
||||
*.bak
|
||||
*.swp
|
||||
*~.nib
|
||||
local.properties
|
||||
.settings/
|
||||
.loadpath
|
||||
|
||||
# Eclipse Core
|
||||
.project
|
||||
|
||||
# External tool builders
|
||||
.externalToolBuilders/
|
||||
|
||||
# Locally stored "Eclipse launch configurations"
|
||||
*.launch
|
||||
|
||||
# CDT-specific
|
||||
.cproject
|
||||
|
||||
# JDT-specific (Eclipse Java Development Tools)
|
||||
.classpath
|
||||
|
||||
# Java annotation processor (APT)
|
||||
.factorypath
|
||||
|
||||
# PDT-specific
|
||||
.buildpath
|
||||
|
||||
# sbteclipse plugin
|
||||
.target
|
||||
|
||||
# TeXlipse plugin
|
||||
.texlipse
|
||||
### C template
|
||||
# Object files
|
||||
*.o
|
||||
*.ko
|
||||
*.obj
|
||||
*.elf
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Libraries
|
||||
*.lib
|
||||
*.a
|
||||
*.la
|
||||
*.lo
|
||||
|
||||
# Shared objects (inc. Windows DLLs)
|
||||
*.dll
|
||||
*.so
|
||||
*.so.*
|
||||
*.dylib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
*.i*86
|
||||
*.x86_64
|
||||
*.hex
|
||||
|
||||
# Debug files
|
||||
*.dSYM/
|
||||
### SBT template
|
||||
# Simple Build Tool
|
||||
# http://www.scala-sbt.org/release/docs/Getting-Started/Directories.html#configuring-version-control
|
||||
|
||||
target/
|
||||
lib_managed/
|
||||
src_managed/
|
||||
project/boot/
|
||||
.history
|
||||
.cache
|
||||
### Emacs template
|
||||
# -*- mode: gitignore; -*-
|
||||
*~
|
||||
\#*\#
|
||||
/.emacs.desktop
|
||||
/.emacs.desktop.lock
|
||||
*.elc
|
||||
auto-save-list
|
||||
tramp
|
||||
.\#*
|
||||
|
||||
# Org-mode
|
||||
.org-id-locations
|
||||
*_archive
|
||||
|
||||
# flymake-mode
|
||||
*_flymake.*
|
||||
|
||||
# eshell files
|
||||
/eshell/history
|
||||
/eshell/lastdir
|
||||
|
||||
# elpa packages
|
||||
/elpa/
|
||||
|
||||
# reftex files
|
||||
*.rel
|
||||
|
||||
# AUCTeX auto folder
|
||||
/auto/
|
||||
|
||||
# cask packages
|
||||
.cask/
|
||||
### Vim template
|
||||
[._]*.s[a-w][a-z]
|
||||
[._]s[a-w][a-z]
|
||||
*.un~
|
||||
Session.vim
|
||||
.netrwhist
|
||||
*~
|
||||
### JetBrains template
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio
|
||||
|
||||
*.iml
|
||||
|
||||
## Directory-based project format:
|
||||
.idea/
|
||||
# if you remove the above rule, at least ignore the following:
|
||||
|
||||
# User-specific stuff:
|
||||
# .idea/workspace.xml
|
||||
# .idea/tasks.xml
|
||||
# .idea/dictionaries
|
||||
|
||||
# Sensitive or high-churn files:
|
||||
# .idea/dataSources.ids
|
||||
# .idea/dataSources.xml
|
||||
# .idea/sqlDataSources.xml
|
||||
# .idea/dynamic.xml
|
||||
# .idea/uiDesigner.xml
|
||||
|
||||
# Gradle:
|
||||
# .idea/gradle.xml
|
||||
# .idea/libraries
|
||||
|
||||
# Mongo Explorer plugin:
|
||||
# .idea/mongoSettings.xml
|
||||
|
||||
## File-based project format:
|
||||
*.ipr
|
||||
*.iws
|
||||
|
||||
## Plugin-specific files:
|
||||
|
||||
# IntelliJ
|
||||
/out/
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
### C++ template
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
*.obj
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
|
||||
# Fortran module files
|
||||
*.mod
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
*.a
|
||||
*.lib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
### OSX template
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Icon must end with two \r
|
||||
Icon
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
### Xcode template
|
||||
# Xcode
|
||||
#
|
||||
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
|
||||
|
||||
## Build generated
|
||||
build/
|
||||
DerivedData
|
||||
|
||||
## Various settings
|
||||
*.pbxuser
|
||||
!default.pbxuser
|
||||
*.mode1v3
|
||||
!default.mode1v3
|
||||
*.mode2v3
|
||||
!default.mode2v3
|
||||
*.perspectivev3
|
||||
!default.perspectivev3
|
||||
xcuserdata
|
||||
|
||||
## Other
|
||||
*.xccheckout
|
||||
*.moved-aside
|
||||
*.xcuserstate
|
||||
### Scala template
|
||||
*.class
|
||||
*.log
|
||||
/.bsp
|
||||
|
||||
# sbt specific
|
||||
.cache
|
||||
.history
|
||||
.lib/
|
||||
dist/*
|
||||
target/
|
||||
lib_managed/
|
||||
src_managed/
|
||||
project/boot/
|
||||
project/plugins/project/
|
||||
|
||||
# Scala-IDE specific
|
||||
.scala_dependencies
|
||||
.worksheet
|
||||
### Java template
|
||||
*.class
|
||||
|
||||
# Mobile Tools for Java (J2ME)
|
||||
.mtj.tmp/
|
||||
|
||||
# Package Files #
|
||||
*.jar
|
||||
*.war
|
||||
*.ear
|
||||
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
hs_err_pid*
|
||||
|
||||
verilog/*.txt
|
||||
verilog/basys3/*
|
||||
verilog/pynq/*
|
||||
verilog/verilator/*
|
||||
!verilog/basys3/test.v
|
||||
!verilog/pynq/design_1_wrapper.v
|
||||
!verilog/pynq/test.v
|
||||
!verilog/pynq/TMDS_PLLVR.v
|
||||
!verilog/verilator/sim_main.cpp
|
||||
*.jou
|
||||
*.log
|
||||
.Xil
|
||||
vivado/basys3/riscv-basys3
|
||||
vivado/pynq/riscv-pynq
|
||||
vivado/pynq/NA
|
||||
.vscode
|
||||
.metals
|
||||
47
lab2/Makefile
Normal file
47
lab2/Makefile
Normal file
@@ -0,0 +1,47 @@
|
||||
# Copyright 2021 Howard Lau
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
test:
|
||||
sbt test
|
||||
|
||||
verilator:
|
||||
sbt "runMain board.verilator.VerilogGenerator"
|
||||
cd verilog/verilator && verilator --trace --exe --cc sim_main.cpp Top.v && make -C obj_dir -f VTop.mk
|
||||
|
||||
verilator-sim: verilator
|
||||
cd verilog/verilator && obj_dir/VTop $(SIM_TIME)
|
||||
|
||||
basys3:
|
||||
sbt "runMain board.basys3.VerilogGenerator"
|
||||
pynq:
|
||||
sbt "runMain board.pynq.VerilogGenerator"
|
||||
|
||||
bitstream-basys3: basys3
|
||||
cd vivado/basys3 && vivado -mode batch -source generate_bitstream.tcl
|
||||
|
||||
program-basys3: bitstream-basys3
|
||||
cd vivado/basys3 && vivado -mode batch -source program_device.tcl
|
||||
|
||||
vivado-sim-basys3: basys3
|
||||
cd vivado/basys3 && vivado -mode batch -source run_simulation.tcl
|
||||
bitstream-pynq: pynq
|
||||
cd vivado/pynq && vivado -mode batch -source generate_bitstream.tcl
|
||||
|
||||
program-pynq: bitstream-pynq
|
||||
cd vivado/pynq && vivado -mode batch -source program_device.tcl
|
||||
|
||||
vivado-sim-pynq: pynq
|
||||
cd vivado/pynq && vivado -mode batch -source run_simulation.tcl
|
||||
|
||||
.PHONY: basys3 verilator test bitstream program verilator-sim vivado-sim
|
||||
24
lab2/build.sbt
Normal file
24
lab2/build.sbt
Normal file
@@ -0,0 +1,24 @@
|
||||
import sbt.Keys.libraryDependencies
|
||||
// See README.md for license details.
|
||||
|
||||
ThisBuild / scalaVersion := "2.13.10"
|
||||
ThisBuild / version := "0.1.0"
|
||||
ThisBuild / organization := "io.github.howardlau1999"
|
||||
|
||||
val chiselVersion = "3.6.0"
|
||||
|
||||
lazy val root = (project in file("."))
|
||||
.settings(
|
||||
name := "yatcpu",
|
||||
libraryDependencies ++= Seq(
|
||||
"edu.berkeley.cs" %% "chisel3" % chiselVersion,
|
||||
"edu.berkeley.cs" %% "chiseltest" % "0.6.0" % "test",
|
||||
),
|
||||
scalacOptions ++= Seq(
|
||||
"-language:reflectiveCalls",
|
||||
"-deprecation",
|
||||
"-feature",
|
||||
"-Xcheckinit",
|
||||
),
|
||||
addCompilerPlugin("edu.berkeley.cs" % "chisel3-plugin" % chiselVersion cross CrossVersion.full),
|
||||
)
|
||||
169
lab2/coremark/yatcpu/core_portme.c
Normal file
169
lab2/coremark/yatcpu/core_portme.c
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC)
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
Original Author: Shay Gal-on
|
||||
*/
|
||||
#include "coremark.h"
|
||||
#include "core_portme.h"
|
||||
|
||||
#if VALIDATION_RUN
|
||||
volatile ee_s32 seed1_volatile = 0x3415;
|
||||
volatile ee_s32 seed2_volatile = 0x3415;
|
||||
volatile ee_s32 seed3_volatile = 0x66;
|
||||
#endif
|
||||
#if PERFORMANCE_RUN
|
||||
volatile ee_s32 seed1_volatile = 0x0;
|
||||
volatile ee_s32 seed2_volatile = 0x0;
|
||||
volatile ee_s32 seed3_volatile = 0x66;
|
||||
#endif
|
||||
#if PROFILE_RUN
|
||||
volatile ee_s32 seed1_volatile = 0x8;
|
||||
volatile ee_s32 seed2_volatile = 0x8;
|
||||
volatile ee_s32 seed3_volatile = 0x8;
|
||||
#endif
|
||||
volatile ee_s32 seed4_volatile = ITERATIONS;
|
||||
volatile ee_s32 seed5_volatile = 0;
|
||||
/* Porting : Timing functions
|
||||
How to capture time and convert to seconds must be ported to whatever is
|
||||
supported by the platform. e.g. Read value from on board RTC, read value from
|
||||
cpu clock cycles performance counter etc. Sample implementation for standard
|
||||
time.h and windows.h definitions included.
|
||||
*/
|
||||
CORETIMETYPE
|
||||
barebones_clock()
|
||||
{
|
||||
ee_u32 cyclel;
|
||||
__asm__ __volatile__ (
|
||||
"rdcycle %0" : "=r"(cyclel) : :
|
||||
);
|
||||
return cyclel;
|
||||
}
|
||||
/* Define : TIMER_RES_DIVIDER
|
||||
Divider to trade off timer resolution and total time that can be
|
||||
measured.
|
||||
|
||||
Use lower values to increase resolution, but make sure that overflow
|
||||
does not occur. If there are issues with the return value overflowing,
|
||||
increase this value.
|
||||
*/
|
||||
#define GETMYTIME(_t) (*_t = barebones_clock())
|
||||
#define MYTIMEDIFF(fin, ini) ((fin) - (ini))
|
||||
#define TIMER_RES_DIVIDER 1
|
||||
#define SAMPLE_TIME_IMPLEMENTATION 1
|
||||
#define EE_TICKS_PER_SEC (CLOCKS_PER_SEC / TIMER_RES_DIVIDER)
|
||||
|
||||
/** Define Host specific (POSIX), or target specific global time variables. */
|
||||
static CORETIMETYPE start_time_val, stop_time_val;
|
||||
|
||||
/* Function : start_time
|
||||
This function will be called right before starting the timed portion of
|
||||
the benchmark.
|
||||
|
||||
Implementation may be capturing a system timer (as implemented in the
|
||||
example code) or zeroing some system parameters - e.g. setting the cpu clocks
|
||||
cycles to 0.
|
||||
*/
|
||||
void
|
||||
start_time(void)
|
||||
{
|
||||
GETMYTIME(&start_time_val);
|
||||
}
|
||||
/* Function : stop_time
|
||||
This function will be called right after ending the timed portion of the
|
||||
benchmark.
|
||||
|
||||
Implementation may be capturing a system timer (as implemented in the
|
||||
example code) or other system parameters - e.g. reading the current value of
|
||||
cpu cycles counter.
|
||||
*/
|
||||
void
|
||||
stop_time(void)
|
||||
{
|
||||
GETMYTIME(&stop_time_val);
|
||||
}
|
||||
/* Function : get_time
|
||||
Return an abstract "ticks" number that signifies time on the system.
|
||||
|
||||
Actual value returned may be cpu cycles, milliseconds or any other
|
||||
value, as long as it can be converted to seconds by <time_in_secs>. This
|
||||
methodology is taken to accommodate any hardware or simulated platform. The
|
||||
sample implementation returns millisecs by default, and the resolution is
|
||||
controlled by <TIMER_RES_DIVIDER>
|
||||
*/
|
||||
CORE_TICKS
|
||||
get_time(void)
|
||||
{
|
||||
CORE_TICKS elapsed
|
||||
= (CORE_TICKS)(MYTIMEDIFF(stop_time_val, start_time_val));
|
||||
return elapsed;
|
||||
}
|
||||
/* Function : time_in_secs
|
||||
Convert the value returned by get_time to seconds.
|
||||
|
||||
The <secs_ret> type is used to accommodate systems with no support for
|
||||
floating point. Default implementation implemented by the EE_TICKS_PER_SEC
|
||||
macro above.
|
||||
*/
|
||||
secs_ret
|
||||
time_in_secs(CORE_TICKS ticks)
|
||||
{
|
||||
secs_ret retval = ((secs_ret)ticks) / (secs_ret)EE_TICKS_PER_SEC;
|
||||
return retval;
|
||||
}
|
||||
|
||||
ee_u32 default_num_contexts = 1;
|
||||
|
||||
/* Function : portable_init
|
||||
Target specific initialization code
|
||||
Test for some common mistakes.
|
||||
*/
|
||||
void
|
||||
portable_init(core_portable *p, int *argc, char *argv[])
|
||||
{
|
||||
if (sizeof(ee_ptr_int) != sizeof(ee_u8 *))
|
||||
{
|
||||
ee_printf(
|
||||
"ERROR! Please define ee_ptr_int to a type that holds a "
|
||||
"pointer!\n");
|
||||
}
|
||||
if (sizeof(ee_u32) != 4)
|
||||
{
|
||||
ee_printf("ERROR! Please define ee_u32 to a 32b unsigned type!\n");
|
||||
}
|
||||
p->portable_id = 1;
|
||||
}
|
||||
/* Function : portable_fini
|
||||
Target specific final code
|
||||
*/
|
||||
void
|
||||
portable_fini(core_portable *p)
|
||||
{
|
||||
p->portable_id = 0;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
__mulsi3 (unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int r = 0;
|
||||
|
||||
while (a)
|
||||
{
|
||||
if (a & 1)
|
||||
r += b;
|
||||
a >>= 1;
|
||||
b <<= 1;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
211
lab2/coremark/yatcpu/core_portme.h
Normal file
211
lab2/coremark/yatcpu/core_portme.h
Normal file
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC)
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
Original Author: Shay Gal-on
|
||||
*/
|
||||
/* Topic : Description
|
||||
This file contains configuration constants required to execute on
|
||||
different platforms
|
||||
*/
|
||||
#ifndef CORE_PORTME_H
|
||||
#define CORE_PORTME_H
|
||||
/************************/
|
||||
/* Data types and settings */
|
||||
/************************/
|
||||
/* Configuration : HAS_FLOAT
|
||||
Define to 1 if the platform supports floating point.
|
||||
*/
|
||||
#ifndef HAS_FLOAT
|
||||
#define HAS_FLOAT 0
|
||||
#endif
|
||||
/* Configuration : HAS_TIME_H
|
||||
Define to 1 if platform has the time.h header file,
|
||||
and implementation of functions thereof.
|
||||
*/
|
||||
#ifndef HAS_TIME_H
|
||||
#define HAS_TIME_H 0
|
||||
#define CLOCKS_PER_SEC 100000000
|
||||
#endif
|
||||
/* Configuration : USE_CLOCK
|
||||
Define to 1 if platform has the time.h header file,
|
||||
and implementation of functions thereof.
|
||||
*/
|
||||
#ifndef USE_CLOCK
|
||||
#define USE_CLOCK 0
|
||||
#endif
|
||||
/* Configuration : HAS_STDIO
|
||||
Define to 1 if the platform has stdio.h.
|
||||
*/
|
||||
#ifndef HAS_STDIO
|
||||
#define HAS_STDIO 0
|
||||
#endif
|
||||
/* Configuration : HAS_PRINTF
|
||||
Define to 1 if the platform has stdio.h and implements the printf
|
||||
function.
|
||||
*/
|
||||
#ifndef HAS_PRINTF
|
||||
#define HAS_PRINTF 0
|
||||
#endif
|
||||
|
||||
/* Definitions : COMPILER_VERSION, COMPILER_FLAGS, MEM_LOCATION
|
||||
Initialize these strings per platform
|
||||
*/
|
||||
#ifndef COMPILER_VERSION
|
||||
#ifdef __GNUC__
|
||||
#define COMPILER_VERSION "GCC"__VERSION__
|
||||
#else
|
||||
#define COMPILER_VERSION "Please put compiler version here (e.g. gcc 4.1)"
|
||||
#endif
|
||||
#endif
|
||||
#ifndef COMPILER_FLAGS
|
||||
#define COMPILER_FLAGS \
|
||||
FLAGS_STR /* "Please put compiler flags here (e.g. -o3)" */
|
||||
#endif
|
||||
#ifndef MEM_LOCATION
|
||||
#define MEM_LOCATION "STACK"
|
||||
#endif
|
||||
|
||||
/* Data Types :
|
||||
To avoid compiler issues, define the data types that need ot be used for
|
||||
8b, 16b and 32b in <core_portme.h>.
|
||||
|
||||
*Imprtant* :
|
||||
ee_ptr_int needs to be the data type used to hold pointers, otherwise
|
||||
coremark may fail!!!
|
||||
*/
|
||||
typedef signed short ee_s16;
|
||||
typedef unsigned short ee_u16;
|
||||
typedef signed int ee_s32;
|
||||
typedef double ee_f32;
|
||||
typedef unsigned char ee_u8;
|
||||
typedef unsigned int ee_u32;
|
||||
typedef ee_u32 ee_ptr_int;
|
||||
typedef ee_u32 ee_size_t;
|
||||
#define NULL ((void *)0)
|
||||
/* align_mem :
|
||||
This macro is used to align an offset to point to a 32b value. It is
|
||||
used in the Matrix algorithm to initialize the input memory blocks.
|
||||
*/
|
||||
#define align_mem(x) (void *)(4 + (((ee_ptr_int)(x)-1) & ~3))
|
||||
|
||||
/* Configuration : CORE_TICKS
|
||||
Define type of return from the timing functions.
|
||||
*/
|
||||
#define CORETIMETYPE ee_u32
|
||||
typedef ee_u32 CORE_TICKS;
|
||||
|
||||
/* Configuration : SEED_METHOD
|
||||
Defines method to get seed values that cannot be computed at compile
|
||||
time.
|
||||
|
||||
Valid values :
|
||||
SEED_ARG - from command line.
|
||||
SEED_FUNC - from a system function.
|
||||
SEED_VOLATILE - from volatile variables.
|
||||
*/
|
||||
#ifndef SEED_METHOD
|
||||
#define SEED_METHOD SEED_VOLATILE
|
||||
#endif
|
||||
|
||||
/* Configuration : MEM_METHOD
|
||||
Defines method to get a block of memry.
|
||||
|
||||
Valid values :
|
||||
MEM_MALLOC - for platforms that implement malloc and have malloc.h.
|
||||
MEM_STATIC - to use a static memory array.
|
||||
MEM_STACK - to allocate the data block on the stack (NYI).
|
||||
*/
|
||||
#ifndef MEM_METHOD
|
||||
#define MEM_METHOD MEM_STATIC
|
||||
#endif
|
||||
|
||||
/* Configuration : MULTITHREAD
|
||||
Define for parallel execution
|
||||
|
||||
Valid values :
|
||||
1 - only one context (default).
|
||||
N>1 - will execute N copies in parallel.
|
||||
|
||||
Note :
|
||||
If this flag is defined to more then 1, an implementation for launching
|
||||
parallel contexts must be defined.
|
||||
|
||||
Two sample implementations are provided. Use <USE_PTHREAD> or <USE_FORK>
|
||||
to enable them.
|
||||
|
||||
It is valid to have a different implementation of <core_start_parallel>
|
||||
and <core_end_parallel> in <core_portme.c>, to fit a particular architecture.
|
||||
*/
|
||||
#ifndef MULTITHREAD
|
||||
#define MULTITHREAD 1
|
||||
#define USE_PTHREAD 0
|
||||
#define USE_FORK 0
|
||||
#define USE_SOCKET 0
|
||||
#endif
|
||||
|
||||
/* Configuration : MAIN_HAS_NOARGC
|
||||
Needed if platform does not support getting arguments to main.
|
||||
|
||||
Valid values :
|
||||
0 - argc/argv to main is supported
|
||||
1 - argc/argv to main is not supported
|
||||
|
||||
Note :
|
||||
This flag only matters if MULTITHREAD has been defined to a value
|
||||
greater then 1.
|
||||
*/
|
||||
#ifndef MAIN_HAS_NOARGC
|
||||
#define MAIN_HAS_NOARGC 1
|
||||
#endif
|
||||
|
||||
/* Configuration : MAIN_HAS_NORETURN
|
||||
Needed if platform does not support returning a value from main.
|
||||
|
||||
Valid values :
|
||||
0 - main returns an int, and return value will be 0.
|
||||
1 - platform does not support returning a value from main
|
||||
*/
|
||||
#ifndef MAIN_HAS_NORETURN
|
||||
#define MAIN_HAS_NORETURN 0
|
||||
#endif
|
||||
|
||||
/* Variable : default_num_contexts
|
||||
Not used for this simple port, must contain the value 1.
|
||||
*/
|
||||
extern ee_u32 default_num_contexts;
|
||||
|
||||
typedef struct CORE_PORTABLE_S
|
||||
{
|
||||
ee_u8 portable_id;
|
||||
} core_portable;
|
||||
|
||||
/* target specific init/fini */
|
||||
void portable_init(core_portable *p, int *argc, char *argv[]);
|
||||
void portable_fini(core_portable *p);
|
||||
|
||||
#if !defined(PROFILE_RUN) && !defined(PERFORMANCE_RUN) \
|
||||
&& !defined(VALIDATION_RUN)
|
||||
#if (TOTAL_DATA_SIZE == 1200)
|
||||
#define PROFILE_RUN 1
|
||||
#elif (TOTAL_DATA_SIZE == 2000)
|
||||
#define PERFORMANCE_RUN 1
|
||||
#else
|
||||
#define VALIDATION_RUN 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
int ee_printf(const char *fmt, ...);
|
||||
|
||||
#endif /* CORE_PORTME_H */
|
||||
92
lab2/coremark/yatcpu/core_portme.mak
Normal file
92
lab2/coremark/yatcpu/core_portme.mak
Normal file
@@ -0,0 +1,92 @@
|
||||
# Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC)
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# Original Author: Shay Gal-on
|
||||
|
||||
#File : core_portme.mak
|
||||
|
||||
# Flag : OUTFLAG
|
||||
# Use this flag to define how to to get an executable (e.g -o)
|
||||
OUTFLAG= -o
|
||||
# Flag : CC
|
||||
# Use this flag to define compiler to use
|
||||
CC = clang
|
||||
# Flag : LD
|
||||
# Use this flag to define compiler to use
|
||||
LD = ld.lld
|
||||
# Flag : AS
|
||||
# Use this flag to define compiler to use
|
||||
AS = clang
|
||||
# Flag : CFLAGS
|
||||
# Use this flag to define compiler options. Note, you can add compiler options from the command line using XCFLAGS="other flags"
|
||||
PORT_CFLAGS = -O0 -g --target=riscv32-unknown-elf -march=rv32i -mabi=ilp32
|
||||
FLAGS_STR = "$(PORT_CFLAGS) $(XCFLAGS) $(XLFLAGS) $(LFLAGS_END)"
|
||||
CFLAGS = $(PORT_CFLAGS) -I$(PORT_DIR) -I. -DFLAGS_STR=\"$(FLAGS_STR)\"
|
||||
#Flag : LFLAGS_END
|
||||
# Define any libraries needed for linking or other flags that should come at the end of the link line (e.g. linker scripts).
|
||||
# Note : On certain platforms, the default clock_gettime implementation is supported but requires linking of librt.
|
||||
SEPARATE_COMPILE=1
|
||||
# Flag : SEPARATE_COMPILE
|
||||
# You must also define below how to create an object file, and how to link.
|
||||
OBJOUT = -o
|
||||
LFLAGS = -T $(PORT_DIR)/link.ld
|
||||
ASFLAGS = -c --target=riscv32-unknown-elf -march=rv32i -mabi=ilp32
|
||||
OFLAG = -o
|
||||
COUT = -c
|
||||
|
||||
LFLAGS_END =
|
||||
# Flag : PORT_SRCS
|
||||
# Port specific source files can be added here
|
||||
# You may also need cvt.c if the fcvt functions are not provided as intrinsics by your compiler!
|
||||
PORT_SRCS = $(PORT_DIR)/core_portme.c $(PORT_DIR)/ee_printf.c $(PORT_DIR)/div.s $(PORT_DIR)/init.s
|
||||
vpath %.c $(PORT_DIR)
|
||||
vpath %.s $(PORT_DIR)
|
||||
|
||||
PORT_OBJS = $(PORT_DIR)/init$(OEXT) $(PORT_DIR)/core_portme$(OEXT) $(PORT_DIR)/ee_printf$(OEXT) $(PORT_DIR)/div$(OEXT)
|
||||
PORT_CLEAN = *$(OEXT) $(OUTFILE).asmbin
|
||||
|
||||
# Flag : LOAD
|
||||
# For a simple port, we assume self hosted compile and run, no load needed.
|
||||
|
||||
# Flag : RUN
|
||||
# For a simple port, we assume self hosted compile and run, simple invocation of the executable
|
||||
|
||||
LOAD = echo "Please set LOAD to the process of loading the executable to the flash"
|
||||
RUN = echo "Please set LOAD to the process of running the executable (e.g. via jtag, or board reset)"
|
||||
|
||||
OEXT = .o
|
||||
EXE = .bin
|
||||
|
||||
$(OPATH)$(PORT_DIR)/%$(OEXT) : %.c
|
||||
$(CC) $(CFLAGS) $(XCFLAGS) $(COUT) $< $(OBJOUT) $@
|
||||
|
||||
$(OPATH)%$(OEXT) : %.c
|
||||
$(CC) $(CFLAGS) $(XCFLAGS) $(COUT) $< $(OBJOUT) $@
|
||||
|
||||
$(OPATH)$(PORT_DIR)/%$(OEXT) : %.s
|
||||
$(AS) $(ASFLAGS) $< $(OBJOUT) $@
|
||||
|
||||
# Target : port_pre% and port_post%
|
||||
# For the purpose of this simple port, no pre or post steps needed.
|
||||
|
||||
.PHONY : port_prebuild port_postbuild port_prerun port_postrun port_preload port_postload
|
||||
port_postbuild: $(OUTFILE)
|
||||
llvm-objcopy -O binary -j .text -j .data $(OUTFILE) $(OUTFILE).asmbin
|
||||
port_pre% port_post% :
|
||||
|
||||
# FLAG : OPATH
|
||||
# Path to the output folder. Default - current folder.
|
||||
OPATH = ./
|
||||
MKDIR = mkdir -p
|
||||
|
||||
127
lab2/coremark/yatcpu/cvt.c
Normal file
127
lab2/coremark/yatcpu/cvt.c
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC)
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#include <math.h>
|
||||
#define CVTBUFSIZE 80
|
||||
static char CVTBUF[CVTBUFSIZE];
|
||||
|
||||
static char *
|
||||
cvt(double arg, int ndigits, int *decpt, int *sign, char *buf, int eflag)
|
||||
{
|
||||
int r2;
|
||||
double fi, fj;
|
||||
char * p, *p1;
|
||||
|
||||
if (ndigits < 0)
|
||||
ndigits = 0;
|
||||
if (ndigits >= CVTBUFSIZE - 1)
|
||||
ndigits = CVTBUFSIZE - 2;
|
||||
r2 = 0;
|
||||
*sign = 0;
|
||||
p = &buf[0];
|
||||
if (arg < 0)
|
||||
{
|
||||
*sign = 1;
|
||||
arg = -arg;
|
||||
}
|
||||
arg = modf(arg, &fi);
|
||||
p1 = &buf[CVTBUFSIZE];
|
||||
|
||||
if (fi != 0)
|
||||
{
|
||||
p1 = &buf[CVTBUFSIZE];
|
||||
while (fi != 0)
|
||||
{
|
||||
fj = modf(fi / 10, &fi);
|
||||
*--p1 = (int)((fj + .03) * 10) + '0';
|
||||
r2++;
|
||||
}
|
||||
while (p1 < &buf[CVTBUFSIZE])
|
||||
*p++ = *p1++;
|
||||
}
|
||||
else if (arg > 0)
|
||||
{
|
||||
while ((fj = arg * 10) < 1)
|
||||
{
|
||||
arg = fj;
|
||||
r2--;
|
||||
}
|
||||
}
|
||||
p1 = &buf[ndigits];
|
||||
if (eflag == 0)
|
||||
p1 += r2;
|
||||
*decpt = r2;
|
||||
if (p1 < &buf[0])
|
||||
{
|
||||
buf[0] = '\0';
|
||||
return buf;
|
||||
}
|
||||
while (p <= p1 && p < &buf[CVTBUFSIZE])
|
||||
{
|
||||
arg *= 10;
|
||||
arg = modf(arg, &fj);
|
||||
*p++ = (int)fj + '0';
|
||||
}
|
||||
if (p1 >= &buf[CVTBUFSIZE])
|
||||
{
|
||||
buf[CVTBUFSIZE - 1] = '\0';
|
||||
return buf;
|
||||
}
|
||||
p = p1;
|
||||
*p1 += 5;
|
||||
while (*p1 > '9')
|
||||
{
|
||||
*p1 = '0';
|
||||
if (p1 > buf)
|
||||
++*--p1;
|
||||
else
|
||||
{
|
||||
*p1 = '1';
|
||||
(*decpt)++;
|
||||
if (eflag == 0)
|
||||
{
|
||||
if (p > buf)
|
||||
*p = '0';
|
||||
p++;
|
||||
}
|
||||
}
|
||||
}
|
||||
*p = '\0';
|
||||
return buf;
|
||||
}
|
||||
|
||||
char *
|
||||
ecvt(double arg, int ndigits, int *decpt, int *sign)
|
||||
{
|
||||
return cvt(arg, ndigits, decpt, sign, CVTBUF, 1);
|
||||
}
|
||||
|
||||
char *
|
||||
ecvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf)
|
||||
{
|
||||
return cvt(arg, ndigits, decpt, sign, buf, 1);
|
||||
}
|
||||
|
||||
char *
|
||||
fcvt(double arg, int ndigits, int *decpt, int *sign)
|
||||
{
|
||||
return cvt(arg, ndigits, decpt, sign, CVTBUF, 0);
|
||||
}
|
||||
|
||||
char *
|
||||
fcvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf)
|
||||
{
|
||||
return cvt(arg, ndigits, decpt, sign, buf, 0);
|
||||
}
|
||||
71
lab2/coremark/yatcpu/div.s
Normal file
71
lab2/coremark/yatcpu/div.s
Normal file
@@ -0,0 +1,71 @@
|
||||
.text
|
||||
.globl __divsi3
|
||||
__divsi3:
|
||||
bltz a0, .L10
|
||||
bltz a1, .L11
|
||||
|
||||
.globl __udivsi3
|
||||
__udivsi3:
|
||||
mv a2, a1
|
||||
mv a1, a0
|
||||
li a0, -1
|
||||
beqz a2, .L5
|
||||
li a3, 1
|
||||
bgeu a2, a1, .L2
|
||||
.L1:
|
||||
blez a2, .L2
|
||||
slli a2, a2, 1
|
||||
slli a3, a3, 1
|
||||
bgtu a1, a2, .L1
|
||||
.L2:
|
||||
li a0, 0
|
||||
.L3:
|
||||
bltu a1, a2, .L4
|
||||
sub a1, a1, a2
|
||||
or a0, a0, a3
|
||||
.L4:
|
||||
srli a3, a3, 1
|
||||
srli a2, a2, 1
|
||||
bnez a3, .L3
|
||||
.L5:
|
||||
ret
|
||||
|
||||
.globl __umodsi3
|
||||
__umodsi3:
|
||||
move t0, ra
|
||||
jal __udivsi3
|
||||
move a0, a1
|
||||
jr t0
|
||||
|
||||
.L10:
|
||||
neg a0, a0
|
||||
bgtz a1, .L12
|
||||
|
||||
neg a1, a1
|
||||
j __udivsi3
|
||||
.L11:
|
||||
neg a1, a1
|
||||
.L12:
|
||||
move t0, ra
|
||||
jal __udivsi3
|
||||
neg a0, a0
|
||||
jr t0
|
||||
|
||||
.globl __modsi3
|
||||
__modsi3:
|
||||
move t0, ra
|
||||
bltz a1, .L31
|
||||
bltz a0, .L32
|
||||
.L30:
|
||||
jal __udivsi3
|
||||
move a0, a1
|
||||
jr t0
|
||||
.L31:
|
||||
neg a1, a1
|
||||
bgez a0, .L30
|
||||
.L32:
|
||||
neg a0, a0
|
||||
jal __udivsi3
|
||||
neg a0, a1
|
||||
jr t0
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user