├── Makefile ├── Makefrag-verilator ├── build.sbt ├── others └── idu │ ├── idu.scala │ └── instructions.scala ├── plusarg_reader.v ├── project ├── build.properties └── plugins.sbt ├── sbt-launch.jar ├── src └── main │ ├── resources │ ├── basic.hpp │ ├── csrc │ │ └── sim_dtm.cc │ ├── mem_body.cpp │ ├── mem_body.hpp │ ├── memory_block.cpp │ ├── memory_block.hpp │ ├── sim_dtm.cc │ └── vsrc │ │ ├── plusarg_reader.v │ │ ├── sim_dtm.v │ │ └── sim_monitor.v │ └── scala │ ├── core │ ├── config.scala │ ├── consts.scala │ ├── control.scala │ ├── core.scala │ ├── cpu.scala │ ├── cpu_alu.scala │ ├── cpu_bus.scala │ ├── cpu_regs.scala │ ├── csr.scala │ ├── icache.scala │ ├── instructions.scala │ ├── memory.scala │ ├── memory_blackbox.scala │ └── memory_resourcebox.scala │ ├── core_complex │ ├── core_complex.scala │ ├── generator.scala │ └── test_harness.scala │ ├── ifu │ └── ifu.scala │ └── tl_unit │ ├── TLOriginalSlave.scala │ ├── TLSlaveReg.scala │ ├── dtm.scala │ ├── sim_monitor.scala │ └── test_loader.scala └── verilator_csrc ├── main.cpp └── verilator.h /Makefile: -------------------------------------------------------------------------------- 1 | export TERM=xterm-color 2 | 3 | SBT ?= java -Xmx$(JVM_MEMORY) -Xss8M -XX:MaxPermSize=256M -jar ./sbt-launch.jar 4 | # SBT ?= java -Xmx$(JVM_MEMORY) -Xss8M -XX:MaxPermSize=256M -jar ./sbt/bin/sbt-launch.jar 5 | # SBT ?= sbt -mem 2048 6 | 7 | all: chisel-soc 8 | 9 | include Makefrag-verilator 10 | 11 | PROJ_ROOT = $(shell git rev-parse --show-toplevel) 12 | 13 | generated_dir = $(abspath ./generated-src) 14 | generated_dir_debug = $(abspath ./generated-src-debug) 15 | 16 | # PROJECT ?= freechips.rocketchip.system 17 | PROJECT ?= core_complex 18 | CONFIG ?= $(PROJECT).DefaultConfig 19 | 20 | JAVA_HEAP_SIZE ?= 8G 21 | JAVA_ARGS ?= -Xmx$(JAVA_HEAP_SIZE) -Xss8M -XX:MaxPermSize=256M 22 | 23 | .PHONY = fir_build 24 | 25 | export JAVA_ARGS 26 | 27 | chisel-soc: TestHarness.sv 28 | mkdir -p $(generated_dir_debug)/$(long_name) 29 | $(VERILATOR) $(VERILATOR_FLAGS) -Mdir $(generated_dir_debug)/$(long_name) \ 30 | -o $(abspath $(sim_dir))/$@ $(verilog) $(cppfiles) -LDFLAGS "$(LDFLAGS) -g" --trace \ 31 | -CFLAGS "-I$(generated_dir_debug)/core_complex.$(CONFIG) -g" 32 | $(MAKE) VM_PARALLEL_BUILDS=1 -C $(generated_dir_debug)/$(long_name) -f V$(MODEL).mk 33 | ./$@ 34 | 35 | 36 | TestHarness.sv: 37 | $(SBT) 'runMain $(PROJECT).Generator $(generated_dir_debug) core_complex TestHarness $(PROJECT)' 38 | 39 | mkdir_generated_dir: 40 | mkdir -p $(generated_dir) $(generated_dir_debug) 41 | 42 | gtkwave: 43 | gtkwave ./simx.fst 44 | 45 | clean: 46 | $(RM) -rf test_run_dir target *.v *.fir *.json *.log generated-src-debug *.sv 47 | $(RM) -rf *.d 48 | $(RM) -rf *.graphml 49 | $(RM) -rf *.plusArgs 50 | -------------------------------------------------------------------------------- /Makefrag-verilator: -------------------------------------------------------------------------------- 1 | long_name = $(PROJECT).$(CONFIG) 2 | long_name_fir = $(long_name).fir 3 | 4 | VERILATOR := verilator --cc --exe 5 | VERILATOR_THREADS ?= 4 6 | 7 | CXX ?= g++ 8 | # CXXSRCS := emulator SimDTM SimJTAG remote_bitbang 9 | CXXSRCS := main 10 | CXXFLAGS := $(CXXFLAGS) -std=c++11 -I$(RISCV)/include 11 | LDFLAGS := $(LDFLAGS) -L$(RISCV)/lib -Wl,-rpath,$(RISCV)/lib -L$(abspath $(sim_dir)) -lfesvr -lpthread -lbfd 12 | JVM_MEMORY ?= 2G 13 | 14 | resources := ./src/main/resources 15 | csrc := $(abspath verilator_csrc) 16 | vsrc := $(resources)/vsrc 17 | sim_dir = . 18 | model_header_debug = $(generated_dir_debug)/$(long_name)/V$(MODEL).h 19 | 20 | verilog = $(abspath TestHarness.v) 21 | MODEL ?= TestHarness 22 | 23 | generated_dir_debug = $(abspath ./generated-src-debug) 24 | 25 | VERILATOR_FLAGS := --top-module $(MODEL) \ 26 | +define+PRINTF_COND=1 \ 27 | +define+RANDOMIZE_GARBAGE_ASSIGN \ 28 | +define+STOP_COND=\$$c\(\"done_reset\"\) --assert \ 29 | --trace-fst \ 30 | --bbox-sys \ 31 | --trace-underscore \ 32 | --output-split 20000 \ 33 | --output-split-cfuncs 20000 \ 34 | --threads $(VERILATOR_THREADS) -Wno-UNOPTTHREADS \ 35 | -Wno-STMTDLY --x-assign unique \ 36 | -I$(vsrc) \ 37 | -O3 -CFLAGS "$(CXXFLAGS) -DVERILATOR -DTEST_HARNESS=V$(MODEL) -include $(csrc)/verilator.h" 38 | 39 | cppfiles = $(addprefix $(csrc)/, $(addsuffix .cpp, $(CXXSRCS))) $(abspath $(resources)/sim_dtm.cc) \ 40 | $(abspath $(resources)/mem_body.cpp) $(abspath $(resources)/memory_block.cpp) 41 | 42 | headers = $(wildcard $(csrc)/*.h) 43 | 44 | verilator_bin: 45 | make -C rocketchip/emulator/ verilator 46 | -------------------------------------------------------------------------------- /build.sbt: -------------------------------------------------------------------------------- 1 | def scalacOptionsVersion(scalaVersion: String): Seq[String] = { 2 | Seq() ++ { 3 | // If we're building with Scala > 2.11, enable the compile option 4 | // switch to support our anonymous Bundle definitions: 5 | // https://github.com/scala/bug/issues/10047 6 | CrossVersion.partialVersion(scalaVersion) match { 7 | case Some((2, scalaMajor: Long)) if scalaMajor < 12 => Seq() 8 | case _ => Seq("-Xsource:2.11") 9 | } 10 | } 11 | } 12 | 13 | def javacOptionsVersion(scalaVersion: String): Seq[String] = { 14 | Seq() ++ { 15 | // Scala 2.12 requires Java 8. We continue to generate 16 | // Java 7 compatible code for Scala 2.11 17 | // for compatibility with old clients. 18 | CrossVersion.partialVersion(scalaVersion) match { 19 | case Some((2, scalaMajor: Long)) if scalaMajor < 12 => 20 | Seq("-source", "1.7", "-target", "1.7") 21 | case _ => 22 | Seq("-source", "1.8", "-target", "1.8") 23 | } 24 | } 25 | } 26 | 27 | name := "chisel-soc" 28 | 29 | scalaVersion := "2.12.6" 30 | 31 | crossScalaVersions := Seq("2.12.6", "2.12.3") 32 | 33 | resolvers ++= Seq( 34 | Resolver.sonatypeRepo("snapshots"), 35 | Resolver.sonatypeRepo("releases") 36 | ) 37 | 38 | // Provide a managed dependency on X if -DXVersion="" is supplied on the command line. 39 | val defaultVersions = Map( 40 | "chisel3" -> "3.2.+", 41 | "chisel-iotesters" -> "1.2.+", 42 | "rocketchip" -> "1.2-SNAPSHOT", 43 | "dsptools" -> "1.1.+", 44 | "firrtl" -> "1.2-SNAPSHOT" 45 | ) 46 | 47 | 48 | libraryDependencies ++= (Seq("chisel3", "chisel-iotesters", "dsptools", "rocketchip", "firrtl").map { 49 | dep: String => "edu.berkeley.cs" %% dep % sys.props.getOrElse(dep + "Version", defaultVersions(dep)) }) 50 | 51 | libraryDependencies ++= Seq( 52 | // other dependencies here 53 | "org.scalanlp" %% "breeze" % "0.12", 54 | // native libraries are not included by default. add this if you want them (as of 0.7) 55 | // native libraries greatly improve performance, but increase jar sizes. 56 | // It also packages various blas implementations, which have licenses that may or may not 57 | // be compatible with the Apache License. No GPL code, as best I know. 58 | "org.scalanlp" %% "breeze-natives" % "0.13", 59 | // the visualization library is distributed separately as well. 60 | // It depends on LGPL code. 61 | "org.scalanlp" %% "breeze-viz" % "0.13" 62 | ) 63 | 64 | 65 | libraryDependencies ++= Seq( 66 | "com.fasterxml.jackson.module" %% "jackson-module-scala" % "2.10.0", 67 | "org.scalatest" %% "scalatest" % "2.1.3" % "test" 68 | ) 69 | 70 | 71 | resolvers ++= Seq( 72 | // other resolvers here 73 | // if you want to use snapshot builds (currently 0.12-SNAPSHOT), use this. 74 | "Sonatype Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots/", 75 | "Sonatype Releases" at "https://oss.sonatype.org/content/repositories/releases/" 76 | ) 77 | 78 | scalacOptions ++= scalacOptionsVersion(scalaVersion.value) 79 | javacOptions ++= javacOptionsVersion(scalaVersion.value) 80 | 81 | addCompilerPlugin("org.scalamacros" % "paradise" % "2.1.0" cross CrossVersion.full) 82 | // addSbtPlugin("org.xerial.sbt" % "sbt-pack" % "0.9.3") 83 | 84 | // lazy val rocketchip = RootProject(file("rocket-chip")) 85 | // lazy val chisel3 = RootProject(file("chisel3")) 86 | 87 | lazy val root = (project in file(".")) 88 | // .dependsOn(rocketchip) 89 | // .dependsOn(chisel3) 90 | -------------------------------------------------------------------------------- /others/idu/idu.scala: -------------------------------------------------------------------------------- 1 | package core_complex 2 | 3 | import chisel3._ 4 | 5 | class RV32Decoder extends Module { 6 | val table: Array[(BitPat, List[BitPat])] = Array( 7 | LUI -> List(1, 3, 1, GPR, FIELD_RD, 0, SRC1_Z, FIELD_Z, 0, SRC2_Z, FIELD_Z, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0), 8 | AUIPC -> List(1, 4, 1, GPR, FIELD_RD, 0, SRC1_Z, FIELD_Z, 0, SRC2_Z, FIELD_Z, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 9 | JAL -> List(1, 4, 1, GPR, FIELD_RD, 0, SRC1_Z, FIELD_Z, 0, SRC2_Z, FIELD_Z, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 10 | JALR -> List(1, 4, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 0, SRC2_Z, FIELD_Z, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 11 | BEQ -> List(1, 4, 0, TGT_Z, FIELD_Z, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 12 | BNE -> List(1, 4, 0, TGT_Z, FIELD_Z, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 13 | BLT -> List(1, 4, 0, TGT_Z, FIELD_Z, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 14 | BGE -> List(1, 4, 0, TGT_Z, FIELD_Z, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 15 | BLTU -> List(1, 4, 0, TGT_Z, FIELD_Z, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 16 | BGEU -> List(1, 4, 0, TGT_Z, FIELD_Z, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 17 | LB -> List(1, 1, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 0, SRC2_Z, FIELD_Z, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 18 | LH -> List(1, 1, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 0, SRC2_Z, FIELD_Z, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 19 | LW -> List(1, 1, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 0, SRC2_Z, FIELD_Z, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 20 | LD -> List(1, 1, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 0, SRC2_Z, FIELD_Z, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 21 | LBU -> List(1, 1, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 0, SRC2_Z, FIELD_Z, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 22 | LHU -> List(1, 1, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 0, SRC2_Z, FIELD_Z, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 23 | LWU -> List(1, 1, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 0, SRC2_Z, FIELD_Z, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 24 | SB -> List(1, 2, 0, TGT_Z, FIELD_Z, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 25 | SH -> List(1, 2, 0, TGT_Z, FIELD_Z, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 26 | SW -> List(1, 2, 0, TGT_Z, FIELD_Z, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 27 | SD -> List(1, 2, 0, TGT_Z, FIELD_Z, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 28 | ADDI -> List(1, 3, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 0, SRC2_Z, FIELD_Z, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0), 29 | SLTI -> List(1, 3, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 0, SRC2_Z, FIELD_Z, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0), 30 | SLTIU -> List(1, 3, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 0, SRC2_Z, FIELD_Z, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0), 31 | XORI -> List(1, 3, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 0, SRC2_Z, FIELD_Z, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0), 32 | ORI -> List(1, 3, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 0, SRC2_Z, FIELD_Z, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0), 33 | ANDI -> List(1, 3, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 0, SRC2_Z, FIELD_Z, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0), 34 | SLLI -> List(1, 3, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 0, SRC2_Z, FIELD_Z, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0), 35 | SRLI -> List(1, 3, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 0, SRC2_Z, FIELD_Z, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0), 36 | SRAI -> List(1, 3, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 0, SRC2_Z, FIELD_Z, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0), 37 | ADDIW -> List(1, 3, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 0, SRC2_Z, FIELD_Z, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0), 38 | SLLIW -> List(1, 3, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 0, SRC2_Z, FIELD_Z, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0), 39 | SRLIW -> List(1, 3, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 0, SRC2_Z, FIELD_Z, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0), 40 | SRAIW -> List(1, 3, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 0, SRC2_Z, FIELD_Z, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0), 41 | ADD -> List(1, 3, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0), 42 | SUB -> List(1, 3, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0), 43 | SLL -> List(1, 3, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0), 44 | SLT -> List(1, 3, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0), 45 | SLTU -> List(1, 3, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0), 46 | XOR -> List(1, 3, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0), 47 | SRL -> List(1, 3, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0), 48 | SRA -> List(1, 3, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0), 49 | OR -> List(1, 3, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0), 50 | AND -> List(1, 3, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0), 51 | MUL -> List(1, 5, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 52 | MULH -> List(1, 5, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 53 | MULHSU -> List(1, 5, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 54 | MULHU -> List(1, 5, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 55 | DIV -> List(1, 5, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0), 56 | DIVU -> List(1, 5, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0), 57 | REM -> List(1, 5, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0), 58 | REMU -> List(1, 5, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0), 59 | ADDW -> List(1, 3, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0), 60 | SUBW -> List(1, 3, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0), 61 | SLLW -> List(1, 3, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0), 62 | SRLW -> List(1, 3, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0), 63 | SRAW -> List(1, 3, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0), 64 | MULW -> List(1, 5, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 65 | DIVW -> List(1, 5, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0), 66 | DIVUW -> List(1, 5, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0), 67 | REMW -> List(1, 5, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0), 68 | REMUW -> List(1, 5, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0), 69 | FENCE -> List(1, 2, 0, TGT_Z, FIELD_Z, 0, SRC1_Z, FIELD_Z, 0, SRC2_Z, FIELD_Z, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 70 | FENCE_I -> List(1, 2, 0, TGT_Z, FIELD_Z, 1, GPR, FIELD_RS1, 0, SRC2_Z, FIELD_Z, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 71 | LR_W -> List(1, 2, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 0, SRC2_Z, FIELD_Z, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0), 72 | LR_D -> List(1, 2, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 0, SRC2_Z, FIELD_Z, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0), 73 | SC_W -> List(1, 2, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1), 74 | SC_D -> List(1, 2, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1), 75 | AMOSWAP_W -> List(1, 2, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0), 76 | AMOADD_W -> List(1, 2, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0), 77 | AMOXOR_W -> List(1, 2, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0), 78 | AMOAND_W -> List(1, 2, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0), 79 | AMOOR_W -> List(1, 2, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0), 80 | AMOMIN_W -> List(1, 2, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0), 81 | AMOMAX_W -> List(1, 2, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0), 82 | AMOMINU_W -> List(1, 2, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0), 83 | AMOMAXU_W -> List(1, 2, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0), 84 | AMOSWAP_D -> List(1, 2, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0), 85 | AMOADD_D -> List(1, 2, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0), 86 | AMOXOR_D -> List(1, 2, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0), 87 | AMOAND_D -> List(1, 2, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0), 88 | AMOOR_D -> List(1, 2, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0), 89 | AMOMIN_D -> List(1, 2, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0), 90 | AMOMAX_D -> List(1, 2, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0), 91 | AMOMINU_D -> List(1, 2, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0), 92 | AMOMAXU_D -> List(1, 2, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 1, GPR, FIELD_RS2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0), 93 | ECALL -> List(1, 5, 0, TGT_Z, FIELD_Z, 0, SRC1_Z, FIELD_Z, 0, SRC2_Z, FIELD_Z, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0), 94 | EBREAK -> List(1, 5, 0, TGT_Z, FIELD_Z, 0, SRC1_Z, FIELD_Z, 0, SRC2_Z, FIELD_Z, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0), 95 | HALT -> List(1, 5, 0, TGT_Z, FIELD_Z, 0, SRC1_Z, FIELD_Z, 0, SRC2_Z, FIELD_Z, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 96 | URET -> List(1, 5, 0, TGT_Z, FIELD_Z, 0, SRC1_Z, FIELD_Z, 0, SRC2_Z, FIELD_Z, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0), 97 | SRET -> List(1, 5, 0, TGT_Z, FIELD_Z, 0, SRC1_Z, FIELD_Z, 0, SRC2_Z, FIELD_Z, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0), 98 | MRET -> List(1, 5, 0, TGT_Z, FIELD_Z, 0, SRC1_Z, FIELD_Z, 0, SRC2_Z, FIELD_Z, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0), 99 | WFI -> List(1, 5, 0, TGT_Z, FIELD_Z, 0, SRC1_Z, FIELD_Z, 0, SRC2_Z, FIELD_Z, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 100 | CSRRW -> List(1, 5, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 0, SRC2_Z, FIELD_Z, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0), 101 | CSRRS -> List(1, 5, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 0, SRC2_Z, FIELD_Z, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0), 102 | CSRRC -> List(1, 5, 1, GPR, FIELD_RD, 1, GPR, FIELD_RS1, 0, SRC2_Z, FIELD_Z, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0), 103 | CSRRWI -> List(1, 5, 1, GPR, FIELD_RD, 0, SRC1_Z, FIELD_Z, 0, SRC2_Z, FIELD_Z, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0), 104 | CSRRSI -> List(1, 5, 1, GPR, FIELD_RD, 0, SRC1_Z, FIELD_Z, 0, SRC2_Z, FIELD_Z, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0), 105 | CSRRCI -> List(1, 5, 1, GPR, FIELD_RD, 0, SRC1_Z, FIELD_Z, 0, SRC2_Z, FIELD_Z, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0), 106 | SFENCE_VM -> List(1, 2, 0, TGT_Z, FIELD_Z, 1, GPR, FIELD_RS1, 0, SRC2_Z, FIELD_Z, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 107 | ) 108 | } 109 | -------------------------------------------------------------------------------- /others/idu/instructions.scala: -------------------------------------------------------------------------------- 1 | package core_complex 2 | 3 | object Instructions { 4 | 5 | def LUI = BitPat("-------------------------0110111") 6 | def AUIPC = BitPat("-------------------------0010111") 7 | def JAL = BitPat("-------------------------1101111") 8 | def JALR = BitPat("-----------------000-----1100111") 9 | def BEQ = BitPat("-----------------000-----1100011") 10 | def BNE = BitPat("-----------------001-----1100011") 11 | def BLT = BitPat("-----------------100-----1100011") 12 | def BGE = BitPat("-----------------101-----1100011") 13 | def BLTU = BitPat("-----------------110-----1100011") 14 | def BGEU = BitPat("-----------------111-----1100011") 15 | def LB = BitPat("-----------------000-----0000011") 16 | def LH = BitPat("-----------------001-----0000011") 17 | def LW = BitPat("-----------------010-----0000011") 18 | def LD = BitPat("-----------------011-----0000011") 19 | def LBU = BitPat("-----------------100-----0000011") 20 | def LHU = BitPat("-----------------101-----0000011") 21 | def LWU = BitPat("-----------------110-----0000011") 22 | def SB = BitPat("-----------------000-----0100011") 23 | def SH = BitPat("-----------------001-----0100011") 24 | def SW = BitPat("-----------------010-----0100011") 25 | def SD = BitPat("-----------------011-----0100011") 26 | def ADDI = BitPat("-----------------000-----0010011") 27 | def SLTI = BitPat("-----------------010-----0010011") 28 | def SLTIU = BitPat("-----------------011-----0010011") 29 | def XORI = BitPat("-----------------100-----0010011") 30 | def ORI = BitPat("-----------------110-----0010011") 31 | def ANDI = BitPat("-----------------111-----0010011") 32 | def SLLI = BitPat("000000-----------001-----0010011") 33 | def SRLI = BitPat("000000-----------101-----0010011") 34 | def SRAI = BitPat("010000-----------101-----0010011") 35 | def ADDIW = BitPat("-----------------000-----0011011") 36 | def SLLIW = BitPat("000000-----------001-----0011011") 37 | def SRLIW = BitPat("000000-----------101-----0011011") 38 | def SRAIW = BitPat("010000-----------101-----0011011") 39 | def ADD = BitPat("0000000----------000-----0110011") 40 | def SUB = BitPat("0100000----------000-----0110011") 41 | def SLL = BitPat("0000000----------001-----0110011") 42 | def SLT = BitPat("0000000----------010-----0110011") 43 | def SLTU = BitPat("0000000----------011-----0110011") 44 | def XOR = BitPat("0000000----------100-----0110011") 45 | def SRL = BitPat("0000000----------101-----0110011") 46 | def SRA = BitPat("0100000----------101-----0110011") 47 | def OR = BitPat("0000000----------110-----0110011") 48 | def AND = BitPat("0000000----------111-----0110011") 49 | def MUL = BitPat("0000001----------000-----0110011") 50 | def MULH = BitPat("0000001----------001-----0110011") 51 | def MULHSU = BitPat("0000001----------010-----0110011") 52 | def MULHU = BitPat("0000001----------011-----0110011") 53 | def DIV = BitPat("0000001----------100-----0110011") 54 | def DIVU = BitPat("0000001----------101-----0110011") 55 | def REM = BitPat("0000001----------110-----0110011") 56 | def REMU = BitPat("0000001----------111-----0110011") 57 | def ADDW = BitPat("0000000----------000-----0111011") 58 | def SUBW = BitPat("0100000----------000-----0111011") 59 | def SLLW = BitPat("0000000----------001-----0111011") 60 | def SRLW = BitPat("0000000----------101-----0111011") 61 | def SRAW = BitPat("0100000----------101-----0111011") 62 | def MULW = BitPat("0000001----------000-----0111011") 63 | def DIVW = BitPat("0000001----------100-----0111011") 64 | def DIVUW = BitPat("0000001----------101-----0111011") 65 | def REMW = BitPat("0000001----------110-----0111011") 66 | def REMUW = BitPat("0000001----------111-----0111011") 67 | def FENCE = BitPat("0000--------00000000000000001111") 68 | def FENCE_I = BitPat("0000-------------001-----0001111") 69 | def LR_W = BitPat("00010--00000-----010-----0101111") 70 | def LR_D = BitPat("00010--00000-----011-----0101111") 71 | def SC_W = BitPat("00011------------010-----0101111") 72 | def SC_D = BitPat("00011------------011-----0101111") 73 | def AMOSWAP_W = BitPat("00001------------010-----0101111") 74 | def AMOADD_W = BitPat("00000------------010-----0101111") 75 | def AMOXOR_W = BitPat("00100------------010-----0101111") 76 | def AMOAND_W = BitPat("01100------------010-----0101111") 77 | def AMOOR_W = BitPat("01000------------010-----0101111") 78 | def AMOMIN_W = BitPat("10000------------010-----0101111") 79 | def AMOMAX_W = BitPat("10100------------010-----0101111") 80 | def AMOMINU_W = BitPat("11000------------010-----0101111") 81 | def AMOMAXU_W = BitPat("11100------------010-----0101111") 82 | def AMOSWAP_D = BitPat("00001------------011-----0101111") 83 | def AMOADD_D = BitPat("00000------------011-----0101111") 84 | def AMOXOR_D = BitPat("00100------------011-----0101111") 85 | def AMOAND_D = BitPat("01100------------011-----0101111") 86 | def AMOOR_D = BitPat("01000------------011-----0101111") 87 | def AMOMIN_D = BitPat("10000------------011-----0101111") 88 | def AMOMAX_D = BitPat("10100------------011-----0101111") 89 | def AMOMINU_D = BitPat("11000------------011-----0101111") 90 | def AMOMAXU_D = BitPat("11100------------011-----0101111") 91 | def ECALL = BitPat("00000000000000000000000001110011") 92 | def EBREAK = BitPat("00000000000100000000000001110011") 93 | def HALT = BitPat("000000000011-----000000001110011") 94 | def URET = BitPat("00000000001000000000000001110011") 95 | def SRET = BitPat("00010000001000000000000001110011") 96 | def MRET = BitPat("00110000001000000000000001110011") 97 | def WFI = BitPat("00010000010100000000000001110011") 98 | def CSRRW = BitPat("-----------------001-----1110011") 99 | def CSRRS = BitPat("-----------------010-----1110011") 100 | def CSRRC = BitPat("-----------------011-----1110011") 101 | def CSRRWI = BitPat("-----------------101-----1110011") 102 | def CSRRSI = BitPat("-----------------110-----1110011") 103 | def CSRRCI = BitPat("-----------------111-----1110011") 104 | def SFENCE_VM = BitPat("0001001----------000000001110011") 105 | 106 | } -------------------------------------------------------------------------------- /plusarg_reader.v: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | //VCS coverage exclude_file 4 | 5 | // No default parameter values are intended, nor does IEEE 1800-2012 require them (clause A.2.4 param_assignment), 6 | // but Incisive demands them. These default values should never be used. 7 | module plusarg_reader #(parameter FORMAT="borked=%d", DEFAULT=0, WIDTH=1) ( 8 | output [WIDTH-1:0] out 9 | ); 10 | 11 | `ifdef SYNTHESIS 12 | assign out = DEFAULT; 13 | `else 14 | reg [WIDTH-1:0] myplus; 15 | assign out = myplus; 16 | 17 | initial begin 18 | if (!$value$plusargs(FORMAT, myplus)) myplus = DEFAULT; 19 | end 20 | `endif 21 | 22 | endmodule 23 | -------------------------------------------------------------------------------- /project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=1.2.8 2 | -------------------------------------------------------------------------------- /project/plugins.sbt: -------------------------------------------------------------------------------- 1 | logLevel := Level.Warn 2 | addSbtPlugin("com.typesafe.sbt" % "sbt-ghpages" % "0.6.2") 3 | addSbtPlugin("com.typesafe.sbt" % "sbt-site" % "1.3.1") 4 | addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.7.0") 5 | addSbtPlugin("org.xerial.sbt" % "sbt-pack" % "0.9.3") 6 | addSbtPlugin("com.eed3si9n" % "sbt-unidoc" % "0.4.1") 7 | addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.5.1") 8 | -------------------------------------------------------------------------------- /sbt-launch.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msyksphinz-self/chisel-soc/463d550e115a29e2334b86c7c955c88a64fac7b0/sbt-launch.jar -------------------------------------------------------------------------------- /src/main/resources/basic.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, msyksphinz 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of the copyright holder nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #pragma once 29 | 30 | #include 31 | #include 32 | 33 | using DWord_t = int64_t; 34 | using UDWord_t = uint64_t; 35 | using Word_t = int32_t; 36 | using UWord_t = uint32_t; 37 | using HWord_t = int16_t; 38 | using UHWord_t = uint16_t; 39 | using Byte_t = int8_t; 40 | using UByte_t = uint8_t; 41 | #ifdef ARCH_RISCV 42 | using Addr_t = uint64_t; 43 | const int Addr_bitwidth = 64; 44 | #else // ARCH_RISCV 45 | #ifdef ARCH_MIPS64 46 | using Addr_t = uint64_t; 47 | const int Addr_bitwidth = 64; 48 | #else // ARCH_MIPS64 49 | using Addr_t = uint64_t; 50 | const int Addr_bitwidth = 32; 51 | #endif // ARCH_MIPS64 52 | #endif // ARCH_RISCV 53 | using RegAddr_t = uint8_t; 54 | using Size_t = uint8_t; 55 | using Cycle_t = uint64_t; 56 | 57 | using PeId_t = uint32_t; 58 | using ThId_t = uint32_t; 59 | 60 | using InstWord_t = uint32_t; 61 | 62 | #define Size_Byte (static_cast(0)) 63 | #define Size_HWord (static_cast(1)) 64 | #define Size_Word (static_cast(2)) 65 | #define Size_DWord (static_cast(3)) 66 | 67 | 68 | class v2f_class { 69 | private: 70 | uint32_t m_f[2]; 71 | public: 72 | v2f_class (DWord_t value) { 73 | m_f[0] = value & 0x0ffffffffUL; 74 | m_f[1] = (value >> 32) & 0x0ffffffffUL; 75 | } 76 | v2f_class () {} 77 | void SetElem(int idx, Word_t f) { m_f[idx] = f; } 78 | Word_t GetElem(int idx) { return m_f[idx]; } 79 | v2f_class& operator=(DWord_t value) { 80 | m_f[0] = value & 0x0ffffffffUL; 81 | m_f[1] = (value >> 32) & 0x0ffffffffUL; 82 | return *this; 83 | } 84 | operator DWord_t() { 85 | return (static_cast(m_f[1]) << 32) | m_f[0]; 86 | } 87 | }; 88 | using V2f_t = v2f_class; 89 | 90 | // V2D Data-Type 91 | class v2d_class { 92 | private: 93 | UDWord_t m_f[2]; 94 | public: 95 | void SetElem(int idx, UDWord_t f) { m_f[idx] = f; } 96 | UDWord_t GetElem(int idx) { return m_f[idx]; } 97 | inline void Set64(int idx, UDWord_t f) { m_f[idx] = f; } 98 | inline UDWord_t Get64(int idx) { return m_f[idx]; } 99 | }; 100 | using V2d_t = v2d_class; 101 | 102 | 103 | // V4F Data-Type 104 | class v4f_class { 105 | private: 106 | UWord_t m_f[4]; 107 | public: 108 | void SetElem(int idx, UWord_t f) { m_f[idx] = f; } 109 | UWord_t GetElem(int idx) { return m_f[idx]; } 110 | inline void Set64(int idx, UDWord_t f) { 111 | for (int i = 0; i < 2; i++) { 112 | m_f[idx*2+i] = (f >> (i * 32)); 113 | } 114 | } 115 | inline UDWord_t Get64(int idx) { 116 | UDWord_t ret = 0; 117 | for (int i = 1; i >=0; i--) { 118 | ret = (ret << 32) | static_cast(m_f[idx*2+i]); 119 | } 120 | return ret; 121 | } 122 | }; 123 | using V4f_t = v4f_class; 124 | 125 | 126 | // V8H Data-Type 127 | class v8h_class { 128 | private: 129 | UHWord_t m_f[8]; 130 | public: 131 | void SetElem(int idx, HWord_t f) { m_f[idx] = f; } 132 | UHWord_t GetElem(int idx) { return m_f[idx]; } 133 | inline void Set64(int idx, DWord_t f) { 134 | for (int i = 0; i < 4; i++) { 135 | m_f[idx*4+i] = (f >> (i * 16)) & 0xffff; 136 | } 137 | } 138 | inline DWord_t Get64(int idx) { 139 | DWord_t ret = 0; 140 | for (int i = 3; i >=0; i--) { 141 | ret = (ret << 16) | static_cast(m_f[idx*4+i]); 142 | } 143 | return ret; 144 | } 145 | }; 146 | using V8h_t = v8h_class; 147 | 148 | 149 | // V4H Data-Type 150 | class v4h_class { 151 | private: 152 | UHWord_t m_f[4]; 153 | public: 154 | v4h_class () { }; 155 | v4h_class (DWord_t value) { 156 | Set64 (value); 157 | } 158 | void SetElem(int idx, HWord_t f) { m_f[idx] = f; } 159 | UHWord_t GetElem(int idx) { return m_f[idx]; } 160 | v4h_class& operator=(DWord_t value) { 161 | Set64(value); 162 | return *this; 163 | } 164 | inline void Set64(DWord_t f) { 165 | for (int i = 0; i < 4; i++) { 166 | m_f[i] = (f >> (i * 16)) & 0xffff; 167 | } 168 | } 169 | inline DWord_t Get64() { 170 | DWord_t ret = 0; 171 | for (int i = 3; i >=0; i--) { 172 | ret = (ret << 16) | static_cast(m_f[i]); 173 | } 174 | return ret; 175 | } 176 | operator DWord_t() { 177 | return (static_cast(m_f[3]) << 48) | 178 | (static_cast(m_f[2]) << 32) | 179 | (static_cast(m_f[1]) << 16) | 180 | (static_cast(m_f[0]) << 0); 181 | } 182 | }; 183 | using V4h_t = v4h_class; 184 | 185 | typedef union { 186 | float f; 187 | UWord_t w; 188 | } F_W_t; 189 | 190 | typedef union { 191 | double d; 192 | UDWord_t w; 193 | } D_W_t; 194 | 195 | #define HEAD(obj) (obj->head) 196 | #define TAIL(obj) (obj->tail) 197 | #define NEXT(obj) (obj->next) 198 | -------------------------------------------------------------------------------- /src/main/resources/csrc/sim_dtm.cc: -------------------------------------------------------------------------------- 1 | #include "memory_block.hpp" 2 | #include "mem_body.hpp" 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | using FunctionInfo = std::map; 27 | 28 | using FunctionTable = FunctionInfo; 29 | using VariableTable = FunctionInfo; 30 | 31 | // BFD debug information 32 | std::unique_ptr m_func_table; 33 | std::unique_ptr m_gvar_table; 34 | std::unique_ptr m_memory; 35 | 36 | bool elf_loaded = false; 37 | Addr_t m_tohost_addr, m_fromhost_addr; 38 | bool m_tohost_en = false, m_fromhost_en = false; 39 | 40 | int32_t LoadBinary(std::string path_exec, std::string filename, bool is_load_dump); 41 | 42 | extern "C" int debug_tick( 43 | unsigned char *debug_req_valid, 44 | unsigned char debug_req_ready, 45 | int *debug_req_bits_addr, 46 | int *debug_req_bits_data) 47 | { 48 | if (!elf_loaded) { 49 | m_memory = std::unique_ptr (new Memory ()); 50 | 51 | m_func_table = std::unique_ptr (new FunctionTable ()); 52 | m_gvar_table = std::unique_ptr (new VariableTable ()); 53 | 54 | LoadBinary("", 55 | "/home/msyksphinz/riscv64/riscv64-unknown-elf/share/riscv-tests/isa/rv64ui-p-simple", 56 | true); 57 | 58 | elf_loaded = true; 59 | } 60 | 61 | auto m_memory_ptr = m_memory.get(); 62 | static auto m_it = m_memory_ptr->GetIterBegin(); 63 | static Addr_t addr = 0; 64 | 65 | static int state = 0; 66 | 67 | if (debug_req_ready) { 68 | switch (state) { 69 | case 0 : { 70 | if (m_it != m_memory_ptr->GetIterEnd() && 71 | addr < m_it->second->GetBlockSize()) { 72 | uint32_t data = 0; 73 | for (int i = 0; i < 4; i++) { 74 | uint8_t byte = m_it->second->ReadByte (static_cast(addr + i)); 75 | data = byte << (i * 8) | data; 76 | } 77 | 78 | *debug_req_valid = 1; 79 | *debug_req_bits_addr = addr + m_it->second->GetBaseAddr(); 80 | *debug_req_bits_data = data; 81 | fprintf(stderr, "ELF Loading ... Addr = %08x, Data = %08x\n", 82 | *debug_req_bits_addr, 83 | *debug_req_bits_data); 84 | 85 | addr += 4; 86 | if (addr >= m_it->second->GetBlockSize() && m_it != m_memory_ptr->GetIterEnd()) { 87 | m_it ++; 88 | addr = 0; 89 | } 90 | } else if (m_it == m_memory_ptr->GetIterEnd()) { 91 | state = 1; 92 | } 93 | break; 94 | } 95 | case 1 : { 96 | *debug_req_valid = 1; 97 | *debug_req_bits_addr = 0x20000000; 98 | *debug_req_bits_data = 1; 99 | 100 | state = 2; 101 | 102 | break; 103 | } 104 | case 2 : { 105 | *debug_req_valid = 1; 106 | *debug_req_bits_addr = 0x20000004; 107 | *debug_req_bits_data = 1; 108 | 109 | state = 3; 110 | 111 | break; 112 | } 113 | default: { 114 | *debug_req_valid = 0; 115 | *debug_req_bits_addr = 0; 116 | *debug_req_bits_data = 0; 117 | } 118 | } 119 | } else { 120 | *debug_req_valid = 0; 121 | *debug_req_bits_addr = 0; 122 | *debug_req_bits_data = 0; 123 | } 124 | 125 | return 0; 126 | } 127 | 128 | bool g_dump_hex = false; 129 | int32_t LoadBinaryTable (std::string filename, bool is_load_dump); 130 | void LoadFunctionTable (bfd *abfd); 131 | void LoadGVariableTable (bfd *abfd); 132 | static void load_bitfile (bfd *b, asection *section, PTR data); 133 | static void load_hex (bfd *b, asection *section, Memory *p_memory); 134 | 135 | 136 | int32_t LoadBinary(std::string path_exec, std::string filename, bool is_load_dump) 137 | { 138 | g_dump_hex = is_load_dump; 139 | 140 | // open binary 141 | bfd *abfd = bfd_openr (filename.c_str(), NULL); 142 | if (abfd == NULL) { 143 | perror (filename.c_str()); 144 | return -1; 145 | } 146 | 147 | bfd_check_format (abfd, bfd_object); 148 | 149 | bfd_map_over_sections (abfd, load_bitfile, static_cast(m_memory.get())); 150 | 151 | LoadFunctionTable (abfd); 152 | LoadGVariableTable (abfd); 153 | 154 | /* Read Entry Point */ 155 | int fd = open(filename.c_str(), O_RDONLY); 156 | struct stat s; 157 | assert(fd != -1); 158 | if (fstat(fd, &s) < 0) 159 | abort(); 160 | size_t size = s.st_size; 161 | 162 | char* buf = (char*)mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); 163 | assert(buf != MAP_FAILED); 164 | close(fd); 165 | 166 | // assert(size >= sizeof(Elf64_Ehdr)); 167 | // const Elf64_Ehdr* eh64 = (const Elf64_Ehdr*)buf; 168 | // assert(IS_ELF32(*eh64) || IS_ELF64(*eh64)); 169 | 170 | Elf64_Ehdr* eh = (Elf64_Ehdr*)buf; 171 | 172 | 173 | Addr_t entry_address = eh->e_entry; 174 | 175 | const int reset_vec_size = 8; 176 | 177 | if (path_exec != "") { 178 | char szTmp[32]; 179 | char dtb_path_buf[PATH_MAX]; 180 | sprintf(szTmp, "/proc/%d/exe", getpid()); 181 | int bytes = readlink(szTmp, dtb_path_buf, PATH_MAX); 182 | if(bytes >= 0) 183 | dtb_path_buf[bytes] = '\0'; 184 | 185 | std::string dtb_path_str = dtb_path_buf; 186 | int slash_pos = dtb_path_str.rfind("/"); 187 | std::string dtb_path_str_dir = dtb_path_str.substr(0, slash_pos); 188 | std::string dtb_path_str_replace = dtb_path_str_dir + "/riscv64.dtb"; 189 | 190 | FILE *dtb_fp; 191 | if ((dtb_fp = fopen(dtb_path_str_replace.c_str(), "r")) == NULL) { 192 | perror (dtb_path_str_replace.c_str()); 193 | return -1; 194 | } 195 | 196 | // Byte_t dtb_buf; 197 | // Addr_t rom_addr = 0x00001020; 198 | // while (fread(&dtb_buf, sizeof(Byte_t), 1, dtb_fp) == 1) { 199 | // StoreMemoryDebug (rom_addr, &dtb_buf); // To Disable Trace Log 200 | // rom_addr++; 201 | // } 202 | } 203 | 204 | return 0; 205 | } 206 | 207 | 208 | int32_t LoadBinaryTable (std::string filename, bool is_load_dump) 209 | { 210 | g_dump_hex = is_load_dump; 211 | 212 | // open binary 213 | bfd *abfd = bfd_openr (filename.c_str(), NULL); 214 | if (abfd == NULL) { 215 | perror (filename.c_str()); 216 | return -1; 217 | } 218 | 219 | bfd_check_format (abfd, bfd_object); 220 | LoadFunctionTable (abfd); 221 | LoadGVariableTable (abfd); 222 | 223 | return 0; 224 | } 225 | 226 | 227 | void LoadFunctionTable (bfd *abfd) 228 | { 229 | long storage_needed; 230 | asymbol **symbol_table; 231 | long number_of_symbols; 232 | 233 | storage_needed = bfd_get_symtab_upper_bound (abfd); 234 | if (storage_needed < 0) { 235 | std::cerr << "Error storage_needed < 0\n"; 236 | exit (EXIT_FAILURE); 237 | } 238 | if (storage_needed == 0) { 239 | std::cerr << "Error storage_needed == 0\n"; 240 | exit (EXIT_FAILURE); 241 | } 242 | 243 | symbol_table = (asymbol **) malloc (storage_needed); 244 | 245 | number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table); 246 | 247 | if (number_of_symbols < 0) { 248 | std::cerr << "Error: number_of_symbols < 0\n"; 249 | exit (EXIT_FAILURE); 250 | } 251 | for (int i = 0; i < number_of_symbols; i++) { 252 | 253 | if (g_dump_hex) { 254 | fprintf (stderr, "\n", 255 | bfd_asymbol_name (symbol_table[i]), symbol_table[i]->flags, bfd_asymbol_value(symbol_table[i])); 256 | } 257 | if ((symbol_table[i]->flags & BSF_FUNCTION ) != 0x00 || 258 | (symbol_table[i]->flags & BSF_DEBUGGING) != 0x00 || 259 | (symbol_table[i]->flags & BSF_GLOBAL) != 0x00) { 260 | Addr_t addr = bfd_asymbol_value(symbol_table[i]); 261 | 262 | // FunctionInfo *p_func_info = new FunctionInfo (); 263 | // p_func_info->symbol = bfd_asymbol_name(symbol_table[i]); 264 | // p_func_info->addr = addr; 265 | // Insert new function table 266 | // m_func_table->push_back (p_func_info); 267 | m_func_table->insert(std::make_pair(addr, bfd_asymbol_name(symbol_table[i]))); 268 | 269 | if (g_dump_hex) { 270 | std::stringstream str; 271 | str << "\n"; 273 | fprintf (stderr, "%s", str.str().c_str()); 274 | } 275 | } else if ((symbol_table[i]->flags & BSF_LOCAL) != 0x00) { 276 | // fprintf (stdout, "BSF_Local "); 277 | } else { 278 | // fprintf (stdout, "BSF_others "); 279 | } 280 | } 281 | 282 | free (symbol_table); 283 | 284 | if (g_dump_hex) { 285 | fprintf (stderr, "\n"); 286 | } 287 | } 288 | 289 | 290 | void LoadGVariableTable (bfd *abfd) 291 | { 292 | long storage_needed; 293 | asymbol **symbol_table; 294 | long number_of_symbols; 295 | 296 | storage_needed = bfd_get_symtab_upper_bound (abfd); 297 | if (storage_needed < 0) { 298 | std::cerr << "Error storage_needed < 0\n"; 299 | exit (EXIT_FAILURE); 300 | } 301 | if (storage_needed == 0) { 302 | std::cerr << "Error storage_needed == 0\n"; 303 | exit (EXIT_FAILURE); 304 | } 305 | 306 | symbol_table = (asymbol **) malloc (storage_needed); 307 | 308 | number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table); 309 | 310 | if (number_of_symbols < 0) { 311 | std::cerr << "Error: number_of_symbols < 0\n"; 312 | exit (EXIT_FAILURE); 313 | } 314 | for (int i = 0; i < number_of_symbols; i++) { 315 | 316 | // fprintf (stdout, "SymbolName=%s : ", bfd_asymbol_name (symbol_table[i])); 317 | if ((symbol_table[i]->flags & BSF_FUNCTION) != 0x00) { 318 | // fprintf (stdout, "BSF_Function "); 319 | 320 | } else if ((symbol_table[i]->flags & BSF_LOCAL) != 0x00) { 321 | // fprintf (stdout, "BSF_Local %s %08x\n", 322 | 323 | } else if ((symbol_table[i]->flags & BSF_GLOBAL) != 0x00) { 324 | // FunctionInfo *p_gvar_info = new FunctionInfo (); 325 | // p_gvar_info->symbol = bfd_asymbol_name(symbol_table[i]); 326 | // p_gvar_info->addr = bfd_asymbol_value (symbol_table[i]); 327 | // Insert new function table 328 | // m_gvar_table->push_back (p_gvar_info); 329 | m_gvar_table->insert(std::make_pair(bfd_asymbol_value (symbol_table[i]), 330 | bfd_asymbol_name(symbol_table[i]))); 331 | 332 | if (g_dump_hex) { 333 | std::stringstream str; 334 | str << "\n"; 336 | fprintf (stderr, "%s", str.str().c_str()); 337 | } 338 | if (!strcmp(bfd_asymbol_name(symbol_table[i]), "tohost")) { 339 | if (g_dump_hex) { 340 | std::stringstream str; 341 | str << "\n"; 343 | fprintf (stderr, "%s", str.str().c_str()); 344 | } 345 | m_tohost_addr = bfd_asymbol_value(symbol_table[i]); 346 | m_tohost_en = true; 347 | } 348 | if (!strcmp(bfd_asymbol_name(symbol_table[i]), "fromhost")) { 349 | if (g_dump_hex) { 350 | std::stringstream str; 351 | str << "\n"; 353 | fprintf (stderr, "%s", str.str().c_str()); 354 | } 355 | m_fromhost_addr = bfd_asymbol_value(symbol_table[i]); 356 | m_fromhost_en = true; 357 | } 358 | 359 | // if (IsGenSignature() && 360 | // !strcmp(bfd_asymbol_name(symbol_table[i]), "begin_signature")) { 361 | // m_sig_addr_start = bfd_asymbol_value(symbol_table[i]); 362 | // } else { 363 | // m_sig_addr_start = 0x100; 364 | // } 365 | // if (IsGenSignature() && 366 | // !strcmp(bfd_asymbol_name(symbol_table[i]), "end_signature")) { 367 | // m_sig_addr_end = bfd_asymbol_value(symbol_table[i]); 368 | // } else { 369 | // m_sig_addr_end = 0x400; 370 | // } 371 | } else { 372 | // fprintf (stdout, "BSF_others "); 373 | } 374 | } 375 | if (g_dump_hex) { 376 | fprintf (stderr, "\n"); 377 | } 378 | } 379 | 380 | 381 | static void load_bitfile (bfd *b, asection *section, PTR data) 382 | { 383 | Memory *p_memory = static_cast(data); 384 | 385 | if (section->flags & SEC_LINKER_CREATED) return; 386 | if ((section->flags & SEC_CODE) || 387 | (section->flags & SEC_ALLOC)) { 388 | if (!strncmp (".plt", section->name, 4) || 389 | !strncmp (".got", section->name, 4)) { 390 | return; 391 | } 392 | load_hex (b, section, p_memory); 393 | } else if (section->flags & SEC_DATA || 394 | section->flags & SEC_HAS_CONTENTS) { 395 | if (!strncmp (".debug", section->name, 6) || 396 | !strncmp (".comment", section->name, 8)) { 397 | return; 398 | } 399 | 400 | load_hex (b, section, p_memory); 401 | } 402 | 403 | return; 404 | } 405 | 406 | 407 | static void load_hex (bfd *b, asection *section, Memory *p_memory) 408 | { 409 | int size = bfd_section_size (b, section); 410 | std::unique_ptr buf (new Byte_t[size]); 411 | // fprintf (stderr, "\n", size); 412 | 413 | if (!bfd_get_section_contents (b, section, buf.get(), 0, size)) 414 | return; 415 | 416 | /* do hex dump of data */ 417 | for (int i = 0; i < size; i+= 16) { 418 | int j; 419 | 420 | Addr_t addr = section->vma + i; 421 | if (g_dump_hex == true) { 422 | std::stringstream str; 423 | str << std::hex << std::setw(16) << std::setfill('0') << addr; 424 | fprintf (stderr, "%s: ", str.str().c_str()); 425 | } 426 | for (j = 0;j < 16 && (i+j) < size; j++) { 427 | if (g_dump_hex == true) { 428 | fprintf (stderr, "%02x ", static_cast(buf[i+j]) & 0x00ff); 429 | } 430 | p_memory->StoreMemory (addr+j, static_cast(&buf[i+j])); 431 | } 432 | if (g_dump_hex == true) { 433 | for (; j < 16; j++) { 434 | fprintf (stderr, " "); 435 | } 436 | fprintf (stderr, " "); 437 | for (j = 0; j < 16 && j+i < size; j++) { 438 | fprintf (stderr, "%c", isprint (buf[i+j]) ? buf[i+j] : '.'); 439 | } 440 | fprintf (stderr, "\n"); 441 | } 442 | } 443 | 444 | return; 445 | } 446 | -------------------------------------------------------------------------------- /src/main/resources/mem_body.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, msyksphinz 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of the copyright holder nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #include "mem_body.hpp" 38 | 39 | 40 | MemResult operator|(MemResult L, MemResult R) { 41 | return static_cast(static_cast(L) | static_cast(R)); 42 | } 43 | 44 | MemResult operator&(MemResult L, MemResult R) { 45 | return static_cast(static_cast(L) & static_cast(R)); 46 | } 47 | 48 | /*! 49 | * Reference from Memory 50 | * \param addr address 51 | * \param env RISCV environment 52 | */ 53 | template 54 | MemResult Memory::LoadMemory (Addr_t addr, Byte_t *data) 55 | { 56 | const size_t AccSize = sizeof(AccType); 57 | 58 | Addr_t phy_addr = addr; 59 | 60 | MemResult result = SearchMemTable (phy_addr, AccSize, data); 61 | 62 | if (AccSize == 1) { 63 | return result; 64 | } else if ((addr & (AccSize-1)) == 0) { 65 | return result; 66 | } else { 67 | return result | MemResult::MemMisAlign; 68 | } 69 | } 70 | 71 | 72 | template 73 | MemResult Memory::StoreMemory (Addr_t addr, Byte_t *data) 74 | { 75 | const size_t AccSize = sizeof(AccType); 76 | const size_t AccSizeLog = std::log2(AccSize); 77 | const size_t AccSizeMask = (0x01 << AccSizeLog)-1; 78 | 79 | Addr_t phy_addr = addr; 80 | 81 | if (AccSize == 1) { 82 | InsertMemTable (phy_addr, AccSize, data); 83 | return MemResult::MemNoExcept; 84 | } else if ((phy_addr & AccSizeMask) == 0) { 85 | InsertMemTable (phy_addr, AccSize, data); 86 | return MemResult::MemNoExcept; 87 | } else { 88 | return MemResult::MemMisAlign; 89 | } 90 | } 91 | 92 | 93 | MemResult Memory::SearchMemTable (Addr_t addr, size_t acc_size, Byte_t *data) 94 | { 95 | std::unordered_map>::iterator it; 96 | Addr_t baseaddr = addr & BaseMask; 97 | 98 | if ((it = m_memory_vec.find (baseaddr)) != m_memory_vec.end()) { 99 | it->second->ReadBytePtr (addr - baseaddr, acc_size, data); 100 | // for (size_t idx = 0; idx < acc_size; idx++) { 101 | // data[idx] = it->second->ReadByte (addr - baseaddr + idx); 102 | // } 103 | return MemResult::MemNoExcept; 104 | } else { 105 | // *data = 0xa5; 106 | *data = 0x00; 107 | return MemResult::MemNotDefined; 108 | } 109 | 110 | } 111 | 112 | 113 | MemResult Memory::SearchMemTable (Addr_t addr, Byte_t *data) 114 | { 115 | std::unordered_map>::iterator it; 116 | Addr_t baseaddr = addr & BaseMask; 117 | 118 | if ((it = m_memory_vec.find (baseaddr)) != m_memory_vec.end()) { 119 | *data = it->second->ReadByte (static_cast(addr - baseaddr)); 120 | return MemResult::MemNoExcept; 121 | } else { 122 | // *data = 0xa5; 123 | *data = 0x00; 124 | return MemResult::MemNotDefined; 125 | } 126 | } 127 | 128 | 129 | MemResult Memory::InsertMemTable (Addr_t addr, Word_t data) 130 | { 131 | // at first, traverse memory table and check memory region is already registered or not 132 | 133 | std::unordered_map>::iterator it; 134 | Addr_t baseaddr = addr & BaseMask; 135 | 136 | if ((it = m_memory_vec.find (baseaddr)) != m_memory_vec.end()) { 137 | it->second->WriteByte (addr - baseaddr, static_cast(data)); 138 | return MemResult::MemNoExcept; 139 | } 140 | 141 | std::shared_ptr memory_block (new MemoryBlock (baseaddr, (~BaseMask)+1, 0x7)); 142 | 143 | memory_block->WriteByte (addr - baseaddr, static_cast(data)); 144 | m_memory_vec.insert (std::make_pair(baseaddr, memory_block)); 145 | 146 | return MemResult::MemNewRegion; 147 | } 148 | 149 | 150 | MemResult Memory::InsertMemTable (Addr_t addr, size_t acc_size, Byte_t *data) 151 | { 152 | // at first, traverse memory table and check memory region is already registered or not 153 | 154 | std::unordered_map>::iterator it; 155 | Addr_t baseaddr = addr & BaseMask; 156 | 157 | if ((it = m_memory_vec.find (baseaddr)) != m_memory_vec.end()) { 158 | it->second->WriteBytePtr (addr - baseaddr, acc_size, data); 159 | // for (size_t idx = 0; idx < acc_size; idx++) { 160 | // it->second->WriteByte (addr - baseaddr + idx, data[idx]); 161 | // } 162 | return MemResult::MemNoExcept; 163 | } 164 | 165 | std::shared_ptr memory_block (new MemoryBlock (baseaddr, (~BaseMask)+1, 0x7)); 166 | 167 | memory_block->WriteBytePtr (addr - baseaddr, acc_size, data); 168 | // for (size_t idx = 0; idx < acc_size; idx++) { 169 | // memory_block->WriteByte (addr - baseaddr + idx, data[idx]); 170 | // } 171 | m_memory_vec.insert (std::make_pair(baseaddr, memory_block)); 172 | 173 | return MemResult::MemNewRegion; 174 | } 175 | 176 | 177 | void Memory::DumpMemory (FILE *fp) 178 | { 179 | for (auto it = m_memory_vec.begin(); it != m_memory_vec.end(); it++) { 180 | Addr_t base_addr = it->second->GetBaseAddr (); 181 | for (Addr_t addr = 0; addr < it->second->GetBlockSize(); addr+=64) { 182 | std::stringstream str; 183 | str << std::setw(10) << std::hex << std::setfill('0') << (addr + base_addr); 184 | fprintf (fp, "%s : ", str.str().c_str()); 185 | for (int byte_addr = 64-1; byte_addr >= 0; byte_addr--) { 186 | UByte_t data = it->second->ReadByte (static_cast(addr + byte_addr)); 187 | fprintf (fp, "%02x", data); 188 | } 189 | fprintf (fp, "\n"); 190 | } 191 | } 192 | } 193 | 194 | void Memory::GenCleanMemoryFile (FILE *fp) 195 | { 196 | fprintf (fp, "#DATA\n#ORG 00000000\n"); 197 | for (auto it = m_memory_vec.begin(); it != m_memory_vec.end(); it++) { 198 | Addr_t base_addr = it->second->GetBaseAddr (); 199 | for (Addr_t addr = 0; addr < it->second->GetBlockSize(); addr+=4) { 200 | fprintf (fp, "@%08lx 00000000\n", addr + base_addr); 201 | } 202 | } 203 | } 204 | 205 | 206 | 207 | template MemResult Memory::LoadMemory (Addr_t addr, Byte_t *data); 208 | template MemResult Memory::LoadMemory (Addr_t addr, Byte_t *data); 209 | template MemResult Memory::LoadMemory (Addr_t addr, Byte_t *data); 210 | template MemResult Memory::LoadMemory (Addr_t addr, Byte_t *data); 211 | template MemResult Memory::LoadMemory (Addr_t addr, Byte_t *data); 212 | template MemResult Memory::LoadMemory (Addr_t addr, Byte_t *data); 213 | template MemResult Memory::LoadMemory (Addr_t addr, Byte_t *data); 214 | template MemResult Memory::LoadMemory (Addr_t addr, Byte_t *data); 215 | 216 | template MemResult Memory::StoreMemory (Addr_t addr, Byte_t *data); 217 | template MemResult Memory::StoreMemory (Addr_t addr, Byte_t *data); 218 | template MemResult Memory::StoreMemory (Addr_t addr, Byte_t *data); 219 | template MemResult Memory::StoreMemory(Addr_t addr, Byte_t *data); 220 | template MemResult Memory::StoreMemory (Addr_t addr, Byte_t *data); 221 | template MemResult Memory::StoreMemory (Addr_t addr, Byte_t *data); 222 | template MemResult Memory::StoreMemory (Addr_t addr, Byte_t *data); 223 | template MemResult Memory::StoreMemory(Addr_t addr, Byte_t *data); 224 | -------------------------------------------------------------------------------- /src/main/resources/mem_body.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, msyksphinz 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of the copyright holder nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #pragma once 29 | 30 | #include 31 | #include 32 | #include 33 | 34 | #include "memory_block.hpp" 35 | 36 | enum class MemResult { 37 | MemNoExcept = 0, 38 | MemMisAlign = 1 << 0, 39 | MemNotDefined = 1 << 1, 40 | MemNewRegion = 1 << 2, 41 | MemTlbError = 1 << 3 42 | }; 43 | 44 | 45 | class MemoryBlock; 46 | 47 | class Memory 48 | { 49 | private: 50 | std::unordered_map > m_memory_vec; // memory table 51 | static const Addr_t BaseMask = static_cast(~0x00000FFFULL); 52 | 53 | protected: 54 | 55 | MemResult SearchMemTable (Addr_t addr, Byte_t *data); 56 | MemResult SearchMemTable (Addr_t addr, size_t acc_size, Byte_t *data); 57 | MemResult InsertMemTable (Addr_t addr, Word_t data); 58 | MemResult InsertMemTable (Addr_t addr, size_t acc_size, Byte_t *data); 59 | 60 | public: 61 | 62 | auto GetIterBegin() { return m_memory_vec.begin(); } 63 | auto GetIterEnd() { return m_memory_vec.end(); } 64 | 65 | static Addr_t GetBaseMask () { return BaseMask; } 66 | 67 | template MemResult LoadMemory (Addr_t addr, Byte_t *data); 68 | template MemResult StoreMemory (Addr_t addr, Byte_t *data); 69 | void DumpMemory (FILE *fp); 70 | void GenCleanMemoryFile (FILE *fp); 71 | 72 | }; 73 | -------------------------------------------------------------------------------- /src/main/resources/memory_block.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, msyksphinz 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of the copyright holder nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #include "memory_block.hpp" 29 | #include 30 | #include 31 | #include 32 | 33 | MemoryBlock::MemoryBlock (Addr_t baseaddr, Addr_t blocksize, uint8_t permission) 34 | { 35 | m_baseaddr = baseaddr; 36 | m_blocksize = blocksize; 37 | m_permission = permission; 38 | m_memory = std::unique_ptr (new Byte_t[blocksize * sizeof(Byte_t)]); 39 | // memset (m_memory.get(), 0xa5, blocksize * sizeof(Byte_t)); 40 | memset (m_memory.get(), 0x00, blocksize * sizeof(Byte_t)); 41 | } 42 | 43 | 44 | Byte_t MemoryBlock::ReadByte (Addr_t addr) 45 | { 46 | assert(addr < m_blocksize); 47 | return m_memory[addr]; 48 | } 49 | 50 | void MemoryBlock::ReadBytePtr (Addr_t addr, size_t acc_size, Byte_t *data) 51 | { 52 | assert(addr < m_blocksize); 53 | Byte_t *ret_ptr; 54 | memcpy (data, &m_memory[addr], acc_size); 55 | } 56 | 57 | 58 | void MemoryBlock::WriteByte (Addr_t addr, Byte_t data) 59 | { 60 | assert(addr < m_blocksize); 61 | m_memory[addr] = data; 62 | return; 63 | } 64 | 65 | 66 | void MemoryBlock::WriteBytePtr (Addr_t addr, size_t acc_size, Byte_t *data) 67 | { 68 | assert(addr < m_blocksize); 69 | memcpy (&m_memory[addr], data, acc_size); 70 | return; 71 | } 72 | -------------------------------------------------------------------------------- /src/main/resources/memory_block.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, msyksphinz 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of the copyright holder nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #pragma once 29 | 30 | #include 31 | #include 32 | #include "./basic.hpp" 33 | 34 | enum MemoryMode {exec_bit = 0, 35 | write_bit = 1, 36 | read_bit = 2}; 37 | 38 | class MemoryBlock { 39 | 40 | private: 41 | 42 | MemoryMode m_mode; 43 | 44 | Addr_t m_baseaddr; 45 | Addr_t m_blocksize; 46 | uint8_t m_permission; 47 | 48 | std::unique_ptr m_memory; 49 | 50 | public: 51 | 52 | MemoryBlock (Addr_t baseaddr, Addr_t blocksize, uint8_t permission); 53 | 54 | Addr_t GetBaseAddr(void) const { 55 | return m_baseaddr; 56 | } 57 | 58 | Addr_t GetBlockSize (void) const { 59 | return m_blocksize; 60 | } 61 | 62 | uint8_t GetPermission (void) const { 63 | return m_permission; 64 | } 65 | 66 | Byte_t ReadByte (Addr_t addr); 67 | void WriteByte (Addr_t addr, Byte_t data); 68 | void ReadBytePtr (Addr_t addr, size_t acc_size, Byte_t *data); 69 | void WriteBytePtr (Addr_t addr, size_t acc_size, Byte_t *data); 70 | class LessA { 71 | Addr_t m_addr; 72 | public: 73 | bool operator () (const MemoryBlock *const A) { 74 | // fprintf (stdout, "\n", 75 | // m_addr, 76 | // A->GetBaseAddr(), 77 | // A->GetBlockSize()); 78 | return (A->GetBaseAddr() <= m_addr && 79 | m_addr < (A->GetBaseAddr() + A->GetBlockSize())); 80 | } 81 | LessA (Addr_t addr) { m_addr = addr; } 82 | }; 83 | }; 84 | -------------------------------------------------------------------------------- /src/main/resources/sim_dtm.cc: -------------------------------------------------------------------------------- 1 | csrc/sim_dtm.cc -------------------------------------------------------------------------------- /src/main/resources/vsrc/plusarg_reader.v: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | //VCS coverage exclude_file 4 | 5 | // No default parameter values are intended, nor does IEEE 1800-2012 require them (clause A.2.4 param_assignment), 6 | // but Incisive demands them. These default values should never be used. 7 | module plusarg_reader #(parameter FORMAT="borked=%d", DEFAULT=0, WIDTH=1) ( 8 | output [WIDTH-1:0] out 9 | ); 10 | 11 | `ifdef SYNTHESIS 12 | assign out = DEFAULT; 13 | `else 14 | reg [WIDTH-1:0] myplus; 15 | assign out = myplus; 16 | 17 | initial begin 18 | if (!$value$plusargs(FORMAT, myplus)) myplus = DEFAULT; 19 | end 20 | `endif 21 | 22 | endmodule 23 | -------------------------------------------------------------------------------- /src/main/resources/vsrc/sim_dtm.v: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | //VCS coverage exclude_file 3 | 4 | import "DPI-C" function int debug_tick 5 | ( 6 | output bit debug_req_valid, 7 | input bit debug_req_ready, 8 | output int debug_req_bits_addr, 9 | output int debug_req_bits_data 10 | ); 11 | 12 | module sim_dtm( 13 | input clock, 14 | input reset, 15 | 16 | output logic req_valid, 17 | output logic [31:0] req_bits_addr, 18 | output logic [31:0] req_bits_data, 19 | input logic req_ready 20 | ); 21 | 22 | logic __debug_req_valid; 23 | logic [31: 0] __debug_req_bits_addr; 24 | logic [31: 0] __debug_req_bits_data; 25 | 26 | logic req_valid_reg; 27 | logic [31:0] req_bits_addr_reg; 28 | logic [31:0] req_bits_data_reg; 29 | 30 | always_ff @(posedge clock) begin 31 | req_valid_reg <= __debug_req_valid; 32 | req_bits_addr_reg <= __debug_req_bits_addr; 33 | req_bits_data_reg <= __debug_req_bits_data; 34 | end 35 | 36 | assign req_valid = req_valid_reg; 37 | assign req_bits_addr = req_bits_addr_reg; 38 | assign req_bits_data = req_bits_data_reg; 39 | 40 | int debug_tick_val; 41 | 42 | always_ff @(negedge clock) begin 43 | if (reset) begin 44 | end else begin 45 | debug_tick_val = debug_tick( 46 | __debug_req_valid, 47 | req_ready, 48 | __debug_req_bits_addr, 49 | __debug_req_bits_data 50 | ); 51 | end 52 | end 53 | 54 | endmodule // sim_dtm 55 | -------------------------------------------------------------------------------- /src/main/resources/vsrc/sim_monitor.v: -------------------------------------------------------------------------------- 1 | module sim_monitor 2 | ( 3 | input logic clock, 4 | input logic reset, 5 | 6 | input logic [1: 0] dbg_hart_id, 7 | input logic dbg_valid, 8 | 9 | input logic dbg_inst_fetch_req, 10 | input logic [31:0] dbg_inst_fetch_addr, 11 | input logic dbg_inst_fetch_ack, 12 | input logic [31:0] dbg_inst_fetch_rddata, 13 | input logic [2:0] dbg_pc_update_cause, 14 | input logic dbg_inst_valid, 15 | input logic [31:0] dbg_inst_addr, 16 | input logic [31:0] dbg_inst_hex, 17 | input logic dbg_reg_wren, 18 | input logic [4:0] dbg_reg_wraddr, 19 | input logic [63:0] dbg_reg_wrdata, 20 | input logic [63:0] dbg_alu_rdata0, 21 | input logic [4:0] dbg_alu_reg_rs0, 22 | input logic [63:0] dbg_alu_rdata1, 23 | input logic [4:0] dbg_alu_reg_rs1, 24 | input logic [4:0] dbg_alu_func, 25 | input logic dbg_mem_inst_valid, 26 | input logic [4:0] dbg_mem_inst_rd, 27 | input logic [63:0] dbg_mem_alu_res, 28 | input logic [2:0] dbg_csr_cmd, 29 | input logic [11:0] dbg_csr_addr, 30 | input logic [63:0] dbg_csr_wdata, 31 | input logic dbg_data_bus_req, 32 | input logic [1:0] dbg_data_bus_cmd, 33 | input logic [31:0] dbg_data_bus_addr, 34 | input logic [63:0] dbg_data_bus_wrdata, 35 | input logic dbg_data_bus_ack, 36 | input logic [63:0] dbg_data_bus_rddata 37 | ); 38 | 39 | always_ff @ (posedge clock, posedge reset) begin 40 | if (reset) begin 41 | end else begin 42 | if (dbg_valid) begin 43 | $write("%t HART%01d : ", $time, dbg_hart_id); 44 | if (dbg_inst_fetch_req & dbg_inst_fetch_ack) begin 45 | $write("%08x", dbg_inst_fetch_addr); 46 | end else begin 47 | $write(" "); 48 | end 49 | 50 | if (dbg_inst_fetch_req) begin 51 | $write("%08x : ", dbg_inst_fetch_addr); 52 | end else begin 53 | $write(" : "); 54 | end 55 | 56 | if (dbg_inst_fetch_ack) begin 57 | $write("%08x ", dbg_inst_fetch_rddata); 58 | end else begin 59 | $write(" "); 60 | end 61 | 62 | if (dbg_reg_wren) begin 63 | $write("R%02d<=%016x", dbg_reg_wraddr, dbg_reg_wrdata); 64 | end else begin 65 | $write(" "); 66 | end 67 | $write("\n"); 68 | end // if (dbg_valid) 69 | end 70 | end 71 | 72 | endmodule // sim_monitor 73 | -------------------------------------------------------------------------------- /src/main/scala/core/config.scala: -------------------------------------------------------------------------------- 1 | package cpu 2 | 3 | abstract class RVConfig() 4 | { 5 | val xlen = 32 6 | val bus_width = 16 7 | val debug = false 8 | } 9 | 10 | case class RV64IConfig() extends RVConfig 11 | { 12 | override val xlen = 64 13 | override val bus_width = 32 14 | override val debug = true 15 | } 16 | 17 | 18 | case class RV64ISynth() extends RVConfig 19 | { 20 | override val xlen = 64 21 | override val bus_width = 32 22 | override val debug = false 23 | } 24 | -------------------------------------------------------------------------------- /src/main/scala/core/consts.scala: -------------------------------------------------------------------------------- 1 | package cpu 2 | 3 | import chisel3._ 4 | import chisel3.util._ 5 | 6 | object BusConsts 7 | { 8 | val CMD_WR = 1.U(2.W) 9 | val CMD_RD = 2.U(2.W) 10 | val CMD_IDLE = 0.U(2.W) 11 | } 12 | 13 | 14 | object DecodeConsts 15 | { 16 | //************************************ 17 | // Control Signals 18 | 19 | val Y = true.B 20 | val N = false.B 21 | 22 | // RS1 Operand Select Signal 23 | val OP0_SZ = 2.W 24 | def OP0_RS1 = 0.U(OP0_SZ) // Register Source #1 25 | def OP0_IMU = 1.U(OP0_SZ) // immediate, U-type 26 | def OP0_IMZ = 2.U(OP0_SZ) // Zero-extended rs1 field of inst, for CSRI instructions 27 | def OP0_X = 0.U(OP0_SZ) 28 | 29 | // RS2 Operand Select Signal 30 | val OP1_SZ = 2.W 31 | def OP1_RS2 = 0.U(OP1_SZ) // Register Source #2 32 | def OP1_IMI = 1.U(OP1_SZ) // immediate, I-type 33 | def OP1_IMS = 2.U(OP1_SZ) // immediate, S-type 34 | def OP1_PC = 3.U(OP1_SZ) // PC 35 | def OP1_X = 0.U(OP1_SZ) 36 | 37 | // ALU Operation Signal 38 | val ALU_OP_SIZE = 5.W 39 | def ALU_ADD = 1.U(ALU_OP_SIZE) 40 | def ALU_SUB = 2.U(ALU_OP_SIZE) 41 | def ALU_SLL = 3.U(ALU_OP_SIZE) 42 | def ALU_SRL = 4.U(ALU_OP_SIZE) 43 | def ALU_SRA = 5.U(ALU_OP_SIZE) 44 | def ALU_AND = 6.U(ALU_OP_SIZE) 45 | def ALU_OR = 7.U(ALU_OP_SIZE) 46 | def ALU_XOR = 8.U(ALU_OP_SIZE) 47 | def ALU_SLT = 9.U(ALU_OP_SIZE) 48 | def ALU_SLTU = 10.U(ALU_OP_SIZE) 49 | def ALU_SNE = 11.U(ALU_OP_SIZE) 50 | def ALU_SEQ = 12.U(ALU_OP_SIZE) 51 | def ALU_SGE = 13.U(ALU_OP_SIZE) 52 | def ALU_SGEU = 14.U(ALU_OP_SIZE) 53 | def ALU_COPY1 = 15.U(ALU_OP_SIZE) 54 | def ALU_ADDW = 16.U(ALU_OP_SIZE) 55 | def ALU_SUBW = 17.U(ALU_OP_SIZE) 56 | def ALU_SLLW = 18.U(ALU_OP_SIZE) 57 | def ALU_SRLW = 19.U(ALU_OP_SIZE) 58 | def ALU_SRAW = 20.U(ALU_OP_SIZE) 59 | def ALU_COPY2 = 21.U(ALU_OP_SIZE) 60 | def ALU_MUL = 22.U(ALU_OP_SIZE) 61 | def ALU_MULH = 23.U(ALU_OP_SIZE) 62 | def ALU_MULHSU = 24.U(ALU_OP_SIZE) 63 | def ALU_MULHU = 25.U(ALU_OP_SIZE) 64 | def ALU_MULW = 26.U(ALU_OP_SIZE) 65 | def ALU_X = 0.U(ALU_OP_SIZE) 66 | 67 | // Memory Mask Type Signal 68 | val MT_SIZE = 3.W 69 | def MT_B = 1.U(MT_SIZE) 70 | def MT_BU = 2.U(MT_SIZE) 71 | def MT_H = 3.U(MT_SIZE) 72 | def MT_HU = 4.U(MT_SIZE) 73 | def MT_W = 5.U(MT_SIZE) 74 | def MT_WU = 6.U(MT_SIZE) 75 | def MT_D = 7.U(MT_SIZE) 76 | def MT_X = 0.U(MT_SIZE) 77 | 78 | // Memory Functions (read, write, fence) 79 | val MCMD_SIZE = 2.W 80 | def MCMD_WR = 1.U(MCMD_SIZE) 81 | def MCMD_RD = 2.U(MCMD_SIZE) 82 | def MCMD_FE = 3.U(MCMD_SIZE) 83 | def MCMD_X = 0.U(MCMD_SIZE) 84 | } 85 | 86 | 87 | object Causes { 88 | val MisFetch = 0x0 89 | val FetchAccess = 0x1 90 | val IllegalInst = 0x2 91 | val BreakPoint = 0x3 92 | val MisalignLoad = 0x4 93 | val LoadAccess = 0x5 94 | val MisalignStore = 0x6 95 | val StoreAccess = 0x7 96 | val UserEcall = 0x8 97 | val MachineEcall = 0xb 98 | } 99 | -------------------------------------------------------------------------------- /src/main/scala/core/control.scala: -------------------------------------------------------------------------------- 1 | package cpu 2 | 3 | import chisel3._ 4 | import chisel3.util._ 5 | 6 | import Instructions._ 7 | import DecodeConsts._ 8 | import CSR._ 9 | 10 | 11 | object CtlIdx 12 | { 13 | val InstVld = 0 14 | val Op0 = 1 15 | val Op1 = 2 16 | val Alu = 3 17 | val Wb = 4 18 | val WbCsr = 5 19 | val Jal = 6 20 | val Jalr = 7 21 | val Br = 8 22 | val MemV = 9 23 | val MemCmd = 10 24 | val MemType = 11 25 | 26 | } 27 | 28 | 29 | class CtrlSignals extends Bundle() 30 | { 31 | val exe_kill = Output(Bool()) // squash EX stage (exception/mret occurred) 32 | val pc_sel = Output(UInt(3.W)) 33 | val brjmp_sel = Output(Bool()) 34 | val op0_sel = Output(UInt(OP0_SZ)) 35 | val op1_sel = Output(UInt(OP1_SZ)) 36 | val alu_fun = Output(UInt(ALU_OP_SIZE)) 37 | // val wb_en = Output(UInt(2.W)) 38 | val wb_en = Output(Bool()) 39 | val rf_wen = Output(Bool()) 40 | val bypassable = Output(Bool()) // instruction's result can be bypassed 41 | val wbcsr = Output(UInt(CSRCMD_SZ)) 42 | val jal = Output(Bool()) 43 | val jalr = Output(Bool()) 44 | val br = Output(Bool()) 45 | 46 | val mem_v = Output(Bool()) 47 | val mem_cmd = Output(UInt(MCMD_SIZE)) 48 | val mem_type = Output(UInt(MT_SIZE)) 49 | 50 | val exception = Output(Bool()) 51 | } 52 | 53 | 54 | class CpathIo extends Bundle() 55 | { 56 | val inst = Input(UInt(32.W)) 57 | val ctl = new CtrlSignals() 58 | override def clone = { new CpathIo().asInstanceOf[this.type] } 59 | } 60 | 61 | 62 | class CtlPath extends Module 63 | { 64 | val io = IO(new CpathIo()) 65 | io := DontCare 66 | 67 | val csignals = 68 | ListLookup(io.inst, 69 | List(N, OP0_X , OP1_X , ALU_X , N ,CSR.X, N, N, N, N, MCMD_X , MT_X ), 70 | Array( /* val | op1 | op2 | ALU | WB |WB_CSR |JAL | JALR | BR | MEM_V | MEM_CMD | MEM_T */ 71 | /* inst | sel | sel | fcn | | | | | | | | */ 72 | LD -> List(Y, OP0_RS1, OP1_IMI , ALU_ADD , Y, CSR.X, N, N, N, Y, MCMD_RD, MT_D ), 73 | LW -> List(Y, OP0_RS1, OP1_IMI , ALU_ADD , Y, CSR.X, N, N, N, Y, MCMD_RD, MT_W ), 74 | LWU -> List(Y, OP0_RS1, OP1_IMI , ALU_ADD , Y, CSR.X, N, N, N, Y, MCMD_RD, MT_WU ), 75 | LB -> List(Y, OP0_RS1, OP1_IMI , ALU_ADD , Y, CSR.X, N, N, N, Y, MCMD_RD, MT_B ), 76 | LBU -> List(Y, OP0_RS1, OP1_IMI , ALU_ADD , Y, CSR.X, N, N, N, Y, MCMD_RD, MT_BU ), 77 | LH -> List(Y, OP0_RS1, OP1_IMI , ALU_ADD , Y, CSR.X, N, N, N, Y, MCMD_RD, MT_H ), 78 | LHU -> List(Y, OP0_RS1, OP1_IMI , ALU_ADD , Y, CSR.X, N, N, N, Y, MCMD_RD, MT_HU ), 79 | SD -> List(Y, OP0_RS1, OP1_IMS , ALU_ADD , N, CSR.X, N, N, N, Y, MCMD_WR, MT_D ), 80 | SW -> List(Y, OP0_RS1, OP1_IMS , ALU_ADD , N, CSR.X, N, N, N, Y, MCMD_WR, MT_W ), 81 | SB -> List(Y, OP0_RS1, OP1_IMS , ALU_ADD , N, CSR.X, N, N, N, Y, MCMD_WR, MT_B ), 82 | SH -> List(Y, OP0_RS1, OP1_IMS , ALU_ADD , N, CSR.X, N, N, N, Y, MCMD_WR, MT_H ), 83 | 84 | AUIPC -> List(Y, OP0_IMU, OP1_PC , ALU_ADD , Y, CSR.X, N, N, N, N, MCMD_X, MT_X ), 85 | LUI -> List(Y, OP0_IMU, OP1_X , ALU_COPY1 , Y, CSR.X, N, N, N, N, MCMD_X, MT_X ), 86 | 87 | MUL -> List(Y, OP0_RS1, OP1_RS2 , ALU_MUL , Y, CSR.X, N, N, N, N, MCMD_X, MT_X ), 88 | MULH -> List(Y, OP0_RS1, OP1_RS2 , ALU_MULH , Y, CSR.X, N, N, N, N, MCMD_X, MT_X ), 89 | MULHSU -> List(Y, OP0_RS1, OP1_RS2 , ALU_MULHSU, Y, CSR.X, N, N, N, N, MCMD_X, MT_X ), 90 | MULHU -> List(Y, OP0_RS1, OP1_RS2 , ALU_MULHU , Y, CSR.X, N, N, N, N, MCMD_X, MT_X ), 91 | MULW -> List(Y, OP0_RS1, OP1_RS2 , ALU_MULW , Y, CSR.X, N, N, N, N, MCMD_X, MT_X ), 92 | 93 | ADDI -> List(Y, OP0_RS1, OP1_IMI , ALU_ADD , Y, CSR.X, N, N, N, N, MCMD_X, MT_X ), 94 | ANDI -> List(Y, OP0_RS1, OP1_IMI , ALU_AND , Y, CSR.X, N, N, N, N, MCMD_X, MT_X ), 95 | ORI -> List(Y, OP0_RS1, OP1_IMI , ALU_OR , Y, CSR.X, N, N, N, N, MCMD_X, MT_X ), 96 | XORI -> List(Y, OP0_RS1, OP1_IMI , ALU_XOR , Y, CSR.X, N, N, N, N, MCMD_X, MT_X ), 97 | SLTI -> List(Y, OP0_RS1, OP1_IMI , ALU_SLT , Y, CSR.X, N, N, N, N, MCMD_X, MT_X ), 98 | SLTIU -> List(Y, OP0_RS1, OP1_IMI , ALU_SLTU , Y, CSR.X, N, N, N, N, MCMD_X, MT_X ), 99 | SLLI -> List(Y, OP0_RS1, OP1_IMI , ALU_SLL , Y, CSR.X, N, N, N, N, MCMD_X, MT_X ), 100 | SRAI -> List(Y, OP0_RS1, OP1_IMI , ALU_SRA , Y, CSR.X, N, N, N, N, MCMD_X, MT_X ), 101 | SRLI -> List(Y, OP0_RS1, OP1_IMI , ALU_SRL , Y, CSR.X, N, N, N, N, MCMD_X, MT_X ), 102 | 103 | SLL -> List(Y, OP0_RS1, OP1_RS2 , ALU_SLL , Y, CSR.X, N, N, N, N, MCMD_X, MT_X ), 104 | ADD -> List(Y, OP0_RS1, OP1_RS2 , ALU_ADD , Y, CSR.X, N, N, N, N, MCMD_X, MT_X ), 105 | SUB -> List(Y, OP0_RS1, OP1_RS2 , ALU_SUB , Y, CSR.X, N, N, N, N, MCMD_X, MT_X ), 106 | SLT -> List(Y, OP0_RS1, OP1_RS2 , ALU_SLT , Y, CSR.X, N, N, N, N, MCMD_X, MT_X ), 107 | SLTU -> List(Y, OP0_RS1, OP1_RS2 , ALU_SLTU , Y, CSR.X, N, N, N, N, MCMD_X, MT_X ), 108 | AND -> List(Y, OP0_RS1, OP1_RS2 , ALU_AND , Y, CSR.X, N, N, N, N, MCMD_X, MT_X ), 109 | OR -> List(Y, OP0_RS1, OP1_RS2 , ALU_OR , Y, CSR.X, N, N, N, N, MCMD_X, MT_X ), 110 | XOR -> List(Y, OP0_RS1, OP1_RS2 , ALU_XOR , Y, CSR.X, N, N, N, N, MCMD_X, MT_X ), 111 | SRA -> List(Y, OP0_RS1, OP1_RS2 , ALU_SRA , Y, CSR.X, N, N, N, N, MCMD_X, MT_X ), 112 | SRL -> List(Y, OP0_RS1, OP1_RS2 , ALU_SRL , Y, CSR.X, N, N, N, N, MCMD_X, MT_X ), 113 | 114 | ADDIW -> List(Y, OP0_RS1, OP1_IMI , ALU_ADDW , Y, CSR.X, N, N, N, N, MCMD_X, MT_X ), 115 | SLLIW -> List(Y, OP0_RS1, OP1_IMI , ALU_SLLW , Y, CSR.X, N, N, N, N, MCMD_X, MT_X ), 116 | SRLIW -> List(Y, OP0_RS1, OP1_IMI , ALU_SRLW , Y, CSR.X, N, N, N, N, MCMD_X, MT_X ), 117 | SRAIW -> List(Y, OP0_RS1, OP1_IMI , ALU_SRAW , Y, CSR.X, N, N, N, N, MCMD_X, MT_X ), 118 | ADDW -> List(Y, OP0_RS1, OP1_RS2 , ALU_ADDW , Y, CSR.X, N, N, N, N, MCMD_X, MT_X ), 119 | SUBW -> List(Y, OP0_RS1, OP1_RS2 , ALU_SUBW , Y, CSR.X, N, N, N, N, MCMD_X, MT_X ), 120 | SLLW -> List(Y, OP0_RS1, OP1_RS2 , ALU_SLLW , Y, CSR.X, N, N, N, N, MCMD_X, MT_X ), 121 | SRLW -> List(Y, OP0_RS1, OP1_RS2 , ALU_SRLW , Y, CSR.X, N, N, N, N, MCMD_X, MT_X ), 122 | SRAW -> List(Y, OP0_RS1, OP1_RS2 , ALU_SRAW , Y, CSR.X, N, N, N, N, MCMD_X, MT_X ), 123 | 124 | JAL -> List(Y, OP0_X , OP1_X , ALU_X , Y, CSR.X, Y, N, N, N, MCMD_X, MT_X ), 125 | JALR -> List(Y, OP0_RS1, OP1_IMI , ALU_ADD , Y, CSR.X, N, Y, N, N, MCMD_X, MT_X ), 126 | BEQ -> List(Y, OP0_RS1, OP1_RS2 , ALU_SEQ , N, CSR.X, N, N, Y, N, MCMD_X, MT_X ), 127 | BNE -> List(Y, OP0_RS1, OP1_RS2 , ALU_SNE , N, CSR.X, N, N, Y, N, MCMD_X, MT_X ), 128 | BGE -> List(Y, OP0_RS1, OP1_RS2 , ALU_SGE , N, CSR.X, N, N, Y, N, MCMD_X, MT_X ), 129 | BGEU -> List(Y, OP0_RS1, OP1_RS2 , ALU_SGEU , N, CSR.X, N, N, Y, N, MCMD_X, MT_X ), 130 | BLT -> List(Y, OP0_RS1, OP1_RS2 , ALU_SLT , N, CSR.X, N, N, Y, N, MCMD_X, MT_X ), 131 | BLTU -> List(Y, OP0_RS1, OP1_RS2 , ALU_SLTU , N, CSR.X, N, N, Y, N, MCMD_X, MT_X ), 132 | 133 | CSRRWI -> List(Y, OP0_IMZ, OP1_RS2 , ALU_COPY2 , Y, CSR.Exch , N, N, N, N, MCMD_X, MT_X ), 134 | CSRRSI -> List(Y, OP0_IMZ, OP1_RS2 , ALU_COPY2 , Y, CSR.Set , N, N, N, N, MCMD_X, MT_X ), 135 | CSRRCI -> List(Y, OP0_IMZ, OP1_RS2 , ALU_COPY2 , Y, CSR.Clear, N, N, N, N, MCMD_X, MT_X ), 136 | CSRRW -> List(Y, OP0_RS1, OP1_RS2 , ALU_COPY2 , Y, CSR.Exch , N, N, N, N, MCMD_X, MT_X ), 137 | CSRRS -> List(Y, OP0_RS1, OP1_RS2 , ALU_COPY2 , Y, CSR.Set , N, N, N, N, MCMD_X, MT_X ), 138 | CSRRC -> List(Y, OP0_RS1, OP1_RS2 , ALU_COPY2 , Y, CSR.Clear, N, N, N, N, MCMD_X, MT_X ), 139 | 140 | ECALL -> List(Y, OP0_X , OP1_X , ALU_COPY1 , Y, CSR.Inst, N, N, N, N, MCMD_X, MT_X ), 141 | MRET -> List(Y, OP0_X , OP1_X , ALU_COPY1 , Y, CSR.Mret, N, N, N, N, MCMD_X, MT_X ), 142 | DRET -> List(Y, OP0_X , OP1_X , ALU_COPY1 , Y, CSR.Inst, N, N, N, N, MCMD_X, MT_X ), 143 | EBREAK -> List(Y, OP0_X , OP1_X , ALU_COPY1 , Y, CSR.Inst, N, N, N, N, MCMD_X, MT_X ), 144 | WFI -> List(Y, OP0_X , OP1_X , ALU_COPY1 , Y, CSR.Inst, N, N, N, N, MCMD_X, MT_X ), // implemented as a NOP 145 | 146 | FENCE_I -> List(Y, OP0_X , OP1_X , ALU_X , N, CSR.X, N, N, N, N, MCMD_FE, MT_X ), 147 | FENCE -> List(Y, OP0_X , OP1_X , ALU_X , N, CSR.X, N, N, N, N, MCMD_FE, MT_X ) 148 | // we are already sequentially consistent, so no need to honor the fence instruction 149 | )) 150 | 151 | io.ctl.exe_kill := false.B // squash EX stage (exception/mret occurred) 152 | io.ctl.pc_sel := 0.U 153 | io.ctl.brjmp_sel := false.B 154 | io.ctl.op0_sel := csignals(CtlIdx.Op0) 155 | io.ctl.op1_sel := csignals(CtlIdx.Op1) 156 | io.ctl.alu_fun := csignals(CtlIdx.Alu) 157 | io.ctl.wb_en := csignals(CtlIdx.Wb) 158 | io.ctl.rf_wen := false.B 159 | io.ctl.bypassable := false.B // instruction's result can be bypassed 160 | io.ctl.wbcsr := csignals(CtlIdx.WbCsr) 161 | 162 | io.ctl.jal := csignals(CtlIdx.Jal) 163 | io.ctl.jalr := csignals(CtlIdx.Jalr) 164 | io.ctl.br := csignals(CtlIdx.Br) 165 | 166 | io.ctl.mem_v := csignals(CtlIdx.MemV) 167 | io.ctl.mem_cmd := csignals(CtlIdx.MemCmd) 168 | io.ctl.mem_type := csignals(CtlIdx.MemType) 169 | 170 | io.ctl.exception := false.B 171 | 172 | } 173 | -------------------------------------------------------------------------------- /src/main/scala/core/core.scala: -------------------------------------------------------------------------------- 1 | package core_complex 2 | 3 | import chisel3._ 4 | import cpu._ 5 | import chipsalliance.rocketchip.config.Parameters 6 | import chisel3.{Bool, Bundle, Input, Output, RegInit} 7 | import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} 8 | import freechips.rocketchip.tilelink._ 9 | import freechips.rocketchip.tilelink.{TLClientNode, TLClientParameters, TLClientPortParameters} 10 | 11 | class CoreTop [Conf <: RVConfig] (conf: Conf, hartid: Int, name: String)(implicit p: Parameters) extends LazyModule { 12 | val inst_node = TLClientNode(Seq(TLClientPortParameters(Seq(TLClientParameters(name = name + "_inst"))))) 13 | val data_node = TLClientNode(Seq(TLClientPortParameters(Seq(TLClientParameters(name = name + "_name"))))) 14 | 15 | lazy val module = new LazyModuleImp (this) { 16 | val io = IO(new Bundle { 17 | val run = Input(Bool()) 18 | val done = Output(Bool()) 19 | val error = Output(Bool()) 20 | 21 | val dbg_monitor = Output(new CpuDebugMonitor(conf)) 22 | }) 23 | 24 | val (inst_out, inst_edge) = inst_node.out(0) 25 | val (data_out, data_edge) = data_node.out(0) 26 | val baseEnd = 0 27 | val (sizeEnd, sizeOff) = (inst_edge.bundle.sizeBits + baseEnd, baseEnd) 28 | val (sourceEnd, sourceOff) = (inst_edge.bundle.sourceBits + sizeEnd, sizeEnd) 29 | val beatBytes = inst_edge.bundle.dataBits 30 | 31 | val cpu = Module(new Cpu(conf, hartid)) 32 | 33 | cpu.io.run := io.run 34 | 35 | inst_out.a.valid := cpu.io.inst_bus.req 36 | inst_out.a.bits.address := cpu.io.inst_bus.addr 37 | inst_out.a.bits.opcode := TLMessages.Get 38 | inst_out.a.bits.mask := 0xf.U 39 | inst_out.a.bits.size := 2.U 40 | inst_out.a.bits.param := 0.U 41 | inst_out.d.ready := true.B 42 | cpu.io.inst_bus.ready := inst_out.a.ready 43 | cpu.io.inst_bus.ack := inst_out.d.valid 44 | cpu.io.inst_bus.rddata := inst_out.d.bits.data.asSInt 45 | 46 | data_out.a.valid := cpu.io.data_bus.req 47 | data_out.a.bits.address := cpu.io.data_bus.addr 48 | data_out.a.bits.opcode := TLMessages.Get 49 | data_out.a.bits.mask := 0xf.U 50 | data_out.a.bits.size := 2.U 51 | data_out.a.bits.param := 0.U 52 | data_out.d.ready := true.B 53 | cpu.io.data_bus.ack := data_out.d.valid 54 | cpu.io.data_bus.rddata := data_out.d.bits.data.asSInt 55 | 56 | io.dbg_monitor := cpu.io.dbg_monitor 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/scala/core/cpu.scala: -------------------------------------------------------------------------------- 1 | package cpu 2 | 3 | import chisel3._ 4 | import chisel3.util._ 5 | import chisel3.Bool 6 | import DecodeConsts._ 7 | import chisel3.experimental.ChiselEnum 8 | 9 | 10 | class CpuDebugMonitor [Conf <: RVConfig](conf: Conf) extends Bundle { 11 | override def cloneType: this.type = 12 | new CpuDebugMonitor(conf).asInstanceOf[this.type] 13 | 14 | val hart_id = Output(UInt()) 15 | val valid = Output(Bool()) 16 | 17 | val inst_fetch_req = if (conf.debug == true) Output(Bool()) else Output(UInt(0.W)) 18 | val inst_fetch_addr = if (conf.debug == true) Output(UInt(conf.bus_width.W)) else Output(UInt(0.W)) 19 | val inst_fetch_ack = if (conf.debug == true) Output(Bool()) else Output(UInt(0.W)) 20 | val inst_fetch_rddata = if (conf.debug == true) Output(SInt(32.W)) else Output(SInt(0.W)) 21 | 22 | val pc_update_cause = if(conf.debug == true) Output(UInt(3.W)) else Output(UInt(0.W)) 23 | 24 | val inst_valid = if (conf.debug == true) Output(Bool()) else Output(UInt(0.W)) 25 | val inst_addr = if (conf.debug == true) Output(UInt(conf.bus_width.W)) else Output(UInt(0.W)) 26 | val inst_hex = if (conf.debug == true) Output(UInt(32.W)) else Output(UInt(0.W)) 27 | 28 | val reg_wren = if (conf.debug == true) Output(Bool()) else Output(UInt(0.W)) 29 | val reg_wraddr = if (conf.debug == true) Output(UInt(5.W)) else Output(UInt(0.W)) 30 | val reg_wrdata = if (conf.debug == true) Output(SInt(conf.xlen.W)) else Output(SInt(0.W)) 31 | 32 | // ALU 33 | val alu_rdata0 = if (conf.debug == true) Output(SInt(conf.xlen.W)) else Output(SInt(0.W)) 34 | val alu_reg_rs0 = if (conf.debug == true) Output(UInt(5.W)) else Output(UInt(0.W)) 35 | val alu_rdata1 = if (conf.debug == true) Output(SInt(conf.xlen.W)) else Output(SInt(0.W)) 36 | val alu_reg_rs1 = if (conf.debug == true) Output(UInt(5.W)) else Output(UInt(0.W)) 37 | val alu_func = if (conf.debug == true) Output(UInt(ALU_OP_SIZE)) else Output(UInt(0.W)) 38 | 39 | val mem_inst_valid = if (conf.debug == true) Output(Bool()) else Output(UInt(0.W)) 40 | val mem_inst_rd = if (conf.debug == true) Output(UInt(5.W)) else Output(UInt(0.W)) 41 | val mem_alu_res = if (conf.debug == true) Output(SInt(conf.xlen.W)) else Output(SInt(0.W)) 42 | 43 | // CSRFile 44 | val csr_cmd = if (conf.debug == true) Output(UInt(CSR.CSRCMD_SZ)) else Output(UInt(0.W)) 45 | val csr_addr = if (conf.debug == true) Output(UInt(12.W)) else Output(UInt(0.W)) 46 | val csr_wdata = if (conf.debug == true) Output(UInt(conf.xlen.W)) else Output(UInt(0.W)) 47 | 48 | // DataBus 49 | val data_bus_req = if (conf.debug == true) Output(Bool()) else Output(UInt(0.W)) 50 | val data_bus_cmd = if (conf.debug == true) Output(UInt(2.W)) else Output(UInt(0.W)) 51 | val data_bus_addr = if (conf.debug == true) Output(UInt(conf.bus_width.W)) else Output(UInt(0.W)) 52 | val data_bus_wrdata = if (conf.debug == true) Output(SInt(conf.xlen.W)) else Output(SInt(0.W)) 53 | val data_bus_ack = if (conf.debug == true) Output(Bool()) else Output(UInt(0.W)) 54 | val data_bus_rddata = if (conf.debug == true) Output(SInt(conf.xlen.W)) else Output(SInt(0.W)) 55 | } 56 | 57 | 58 | class CpuTopIo [Conf <: RVConfig](conf: Conf) extends Bundle { 59 | val run = Input(Bool()) 60 | val ext_bus = new Bus(conf) 61 | 62 | val dbg_monitor = new CpuDebugMonitor(conf) 63 | } 64 | 65 | 66 | class CpuIo [Conf <: RVConfig](conf: Conf) extends Bundle { 67 | val run = Input(Bool()) 68 | 69 | val inst_bus = new InstBus(conf) 70 | val data_bus = new DataBus(conf) 71 | 72 | val dbg_monitor = new CpuDebugMonitor(conf) 73 | } 74 | 75 | class CpuTop [Conf <: RVConfig](hart_id: Int, conf: Conf) extends Module { 76 | val io = IO (new CpuTopIo(conf)) 77 | 78 | val memory = Module (new CpuMemory(conf)) 79 | 80 | val cpu = Module(new Cpu(conf, hart_id)) 81 | 82 | cpu.io.run := io.run 83 | 84 | // Connect CPU and Memory 85 | memory.io.mem.inst_bus <> cpu.io.inst_bus 86 | memory.io.mem.data_bus <> cpu.io.data_bus 87 | // Memory Load for External Debug 88 | memory.io.mem.ext_bus <> io.ext_bus 89 | 90 | io.dbg_monitor <> cpu.io.dbg_monitor 91 | } 92 | 93 | class Cpu [Conf <: RVConfig](conf: Conf, hart_id: Int) extends Module { 94 | val io = IO (new CpuIo(conf)) 95 | 96 | val cycle = RegInit(0.U(32.W)) 97 | cycle := cycle + 1.U 98 | 99 | val u_cpath = Module (new CtlPath) 100 | val u_regs = Module (new Regs(conf)) 101 | val u_alu = Module (new Alu(conf)) 102 | val u_mem_sext = Module (new SExt(conf)) 103 | val u_csrfile = Module (new CsrFile(conf)) 104 | 105 | val if_inst_addr = RegInit(0x80000000L.U(conf.bus_width.W)) 106 | val if_inst_en = RegInit(true.B) 107 | 108 | // Get Instruction 109 | val dec_inst_data = Wire(UInt(32.W)) 110 | val dec_inst_addr = Reg(UInt(conf.bus_width.W)) 111 | val dec_inst_valid = Wire(Bool()) 112 | 113 | val dec_inst_rs2 = dec_inst_data(24,20) 114 | val dec_inst_rs1 = dec_inst_data(19,15) 115 | val dec_inst_rd = dec_inst_data(11, 7) 116 | 117 | val dec_imm_i = dec_inst_data(31, 20).asSInt 118 | val dec_imm_b = Cat(dec_inst_data(31), dec_inst_data(7), dec_inst_data(30,25), dec_inst_data(11,8)) 119 | val dec_imm_b_sext = Cat(Fill(19,dec_imm_b(11)), dec_imm_b, 0.U) 120 | val dec_imm_s = Cat(dec_inst_data(31, 25), dec_inst_data(11,7)).asSInt 121 | val dec_imm_j = Cat(Fill(11, dec_inst_data(31)), dec_inst_data(31), dec_inst_data(19,12), dec_inst_data(20), dec_inst_data(30,21), 0.U(1.W)) 122 | val dec_imm_j_sext = Cat(Fill(64-21, dec_imm_j(20)), dec_imm_j, 0.U(1.W)) 123 | 124 | val dec_rdata_op0 = Wire(SInt(conf.xlen.W)) 125 | val dec_rdata_op1 = Wire(SInt(conf.xlen.W)) 126 | 127 | val dec_inst_wb_en = u_cpath.io.ctl.wb_en & (dec_inst_rd =/= 0.U) 128 | 129 | val dec_jalr_en = u_cpath.io.ctl.jalr 130 | val dec_jal_en = u_cpath.io.ctl.jal 131 | val dec_br_en = u_cpath.io.ctl.br 132 | val dec_csr_wbcsr = u_cpath.io.ctl.wbcsr 133 | val dec_mret_en = (dec_csr_wbcsr === CSR.Mret) 134 | val dec_ecall_en = (dec_csr_wbcsr === CSR.Inst) 135 | val dec_jump_en = dec_jalr_en | dec_jal_en | dec_br_en | dec_mret_en 136 | 137 | val dec_stall_en = dec_inst_valid & (u_cpath.io.ctl.mem_cmd =/= MCMD_X) 138 | 139 | val wb_mem_rdval = Wire(SInt(conf.xlen.W)) 140 | 141 | val ex_inst_valid = RegNext(dec_inst_valid) 142 | val ex_inst_data = RegNext(dec_inst_data) 143 | val ex_inst_addr = RegNext(dec_inst_addr) 144 | 145 | val ex_inst_rs0 = RegNext (dec_inst_rs1) 146 | val ex_inst_rs1 = RegNext (dec_inst_rs2) 147 | val ex_alu_func = RegNext (u_cpath.io.ctl.alu_fun) 148 | val ex_alu_op0 = Wire (SInt(conf.xlen.W)) 149 | val ex_alu_op1 = Wire (SInt(conf.xlen.W)) 150 | val ex_inst_rd = RegNext (dec_inst_rd) 151 | 152 | val ex_jalr_en = RegNext (dec_jalr_en) 153 | val ex_jal_en = RegNext (dec_jal_en) 154 | val ex_br_en = RegNext (dec_br_en) 155 | val ex_br_jump = ex_br_en & (u_alu.io.res === 1.S) 156 | val ex_mret_en = RegNext (dec_mret_en) 157 | val ex_ecall_en = RegNext (dec_ecall_en) 158 | val ex_jump_en = ex_inst_valid & (ex_jalr_en | ex_jal_en | ex_br_jump | ex_mret_en | ex_ecall_en) 159 | 160 | val ex_op0_sel = RegNext (u_cpath.io.ctl.op0_sel) 161 | val ex_op1_sel = RegNext (u_cpath.io.ctl.op1_sel) 162 | 163 | val ex_imm_i = RegNext (dec_imm_i) 164 | val ex_imm_b_sext = RegNext (dec_imm_b_sext) 165 | val ex_imm_s = RegNext (dec_imm_s) 166 | val ex_imm_j = RegNext (dec_imm_j) 167 | 168 | val ex_inst_wb_en = RegNext (dec_inst_wb_en) 169 | val ex_ctrl_mem_v = RegNext (u_cpath.io.ctl.mem_v) 170 | val ex_ctrl_mem_cmd = RegNext (u_cpath.io.ctl.mem_cmd) 171 | val ex_ctrl_mem_type = RegNext (u_cpath.io.ctl.mem_type) 172 | val ex_rdata_op0 = RegNext (dec_rdata_op0) 173 | val ex_rdata_op1 = RegNext (dec_rdata_op1) 174 | val ex_csr_wbcsr = RegNext (dec_csr_wbcsr) 175 | 176 | val ex_mem_val = Wire(SInt(conf.xlen.W)) 177 | 178 | // 179 | // Memory Access Stage Signals 180 | // 181 | val mem_inst_valid = RegNext(ex_inst_valid) 182 | val mem_inst_data = RegNext(ex_inst_data) 183 | val mem_inst_addr = RegNext(ex_inst_addr) 184 | 185 | val mem_inst_rd = RegNext (ex_inst_rd) 186 | val mem_inst_wb_en = RegNext (ex_inst_wb_en) 187 | val mem_alu_res = RegNext (u_alu.io.res) 188 | 189 | val mem_imm_i = RegNext (ex_imm_i) 190 | 191 | val mem_ctrl_mem_v = RegNext (ex_ctrl_mem_v) 192 | val mem_ctrl_mem_cmd = RegNext (ex_ctrl_mem_cmd) 193 | val mem_ctrl_mem_type = RegNext (ex_ctrl_mem_type) 194 | val mem_rdata_op0 = RegNext (ex_rdata_op0) 195 | val mem_rdata_op1 = RegNext (ex_rdata_op1) 196 | 197 | val mem_mem_val = RegNext (ex_mem_val) 198 | 199 | val mem_jalr_en = RegNext (ex_jalr_en) 200 | val mem_jal_en = RegNext (ex_jal_en) 201 | val mem_br_en = RegNext (ex_br_en) 202 | val mem_mret_en = RegNext (ex_mret_en) 203 | val mem_ecall_en = RegNext (ex_ecall_en) 204 | val mem_csr_wbcsr = RegNext (ex_csr_wbcsr) 205 | 206 | // 207 | // WB-Stage Signals 208 | // 209 | 210 | val wb_inst_valid = RegNext (mem_inst_valid) 211 | val wb_inst_data = RegNext (mem_inst_data) 212 | val wb_inst_addr = RegNext (mem_inst_addr) 213 | 214 | val wb_rdata_op0 = RegNext (mem_rdata_op0) 215 | val wb_rdata_op1 = RegNext (mem_rdata_op1) 216 | 217 | val wb_inst_wb_en = RegNext (mem_inst_wb_en) 218 | val wb_inst_rd = RegNext (mem_inst_rd) 219 | 220 | val wb_alu_res = RegNext (mem_alu_res) 221 | 222 | val wb_imm_i = RegNext (mem_imm_i) 223 | 224 | val wb_jalr_en = RegNext (mem_jalr_en) 225 | val wb_jal_en = RegNext (mem_jal_en) 226 | val wb_br_en = RegNext (mem_br_en) 227 | val wb_mret_en = RegNext (mem_mret_en) 228 | val wb_ecall_en = RegNext (mem_ecall_en) 229 | val wb_csr_wbcsr = RegNext (mem_csr_wbcsr) 230 | 231 | val wb_ctrl_mem_cmd = RegNext (mem_ctrl_mem_cmd) 232 | val wb_ctrl_mem_type = RegNext (mem_ctrl_mem_type) 233 | 234 | val r_wait_ack = RegInit(false.B) 235 | 236 | object FetchSM extends ChiselEnum { 237 | val sInit, sReqWait, sAckWait, sWaitStall = Value 238 | } 239 | 240 | val fetch_sm = RegInit(FetchSM.sInit) 241 | 242 | switch (fetch_sm) { 243 | is(FetchSM.sInit) { 244 | when(io.run) { 245 | fetch_sm := FetchSM.sReqWait 246 | } 247 | } 248 | is(FetchSM.sReqWait) { 249 | when(io.inst_bus.req && io.inst_bus.ready) { 250 | fetch_sm := FetchSM.sAckWait 251 | } 252 | } 253 | is(FetchSM.sAckWait) { 254 | when(io.inst_bus.ack) { 255 | when (dec_stall_en) { 256 | fetch_sm := FetchSM.sWaitStall 257 | } .otherwise { 258 | fetch_sm := FetchSM.sReqWait 259 | } 260 | } 261 | } 262 | is (FetchSM.sWaitStall) { 263 | when (!dec_stall_en) { 264 | fetch_sm := FetchSM.sReqWait 265 | } 266 | } 267 | } 268 | 269 | when(if_inst_en & io.inst_bus.req) { 270 | when (io.inst_bus.ready) { 271 | if_inst_en := io.inst_bus.ack 272 | } .otherwise { 273 | if_inst_en := false.B 274 | } 275 | } .elsewhen (io.inst_bus.ack) { 276 | if_inst_en := true.B 277 | } 278 | 279 | io.inst_bus.req := (fetch_sm === FetchSM.sReqWait) & !(ex_jump_en | dec_stall_en) 280 | io.inst_bus.addr := if_inst_addr 281 | 282 | if_inst_addr := MuxCase (if_inst_addr, Array ( 283 | (ex_inst_valid & ex_jalr_en) -> u_alu.io.res.asUInt, 284 | (ex_inst_valid & ex_jal_en) -> (ex_inst_addr + ex_imm_j), 285 | (ex_inst_valid & ex_br_jump) -> (ex_inst_addr + ex_imm_b_sext), 286 | (ex_inst_valid & ex_mret_en) -> u_csrfile.io.mepc, 287 | (ex_inst_valid & ex_ecall_en) -> u_csrfile.io.mtvec, 288 | ((fetch_sm === FetchSM.sAckWait) && io.inst_bus.ack && !dec_stall_en) -> (if_inst_addr + 4.U), 289 | (fetch_sm === FetchSM.sWaitStall) -> (if_inst_addr + 4.U) 290 | )) 291 | 292 | // if (conf.debug == true) { 293 | // when (if_inst_en & dec_jalr_en) { 294 | // printf("%d : JALR is enable %x, %x\n", cycle, dec_rdata_op0.asUInt, if_inst_addr) 295 | // } 296 | // when (if_inst_en & dec_jal_en) { 297 | // printf("%d : JAL is enable %x, %x\n", cycle, dec_rdata_op0.asUInt, if_inst_addr) 298 | // } 299 | // when (if_inst_en & dec_br_en) { 300 | // printf("%d : BR is enable %x, %x\n", cycle, dec_rdata_op0.asUInt, if_inst_addr) 301 | // } 302 | // when (if_inst_en & dec_mret_en) { 303 | // printf("%d : MRET is enable %x, %x\n", cycle, dec_rdata_op0.asUInt, if_inst_addr) 304 | // } 305 | // when (if_inst_en & dec_ecall_en) { 306 | // printf("%d : ECAL is enable %x, %x\n", cycle, dec_rdata_op0.asUInt, if_inst_addr) 307 | // } 308 | // } 309 | dec_inst_data := io.inst_bus.rddata.asUInt 310 | dec_inst_addr := if_inst_addr 311 | when ((fetch_sm === FetchSM.sAckWait) & io.inst_bus.ack) { 312 | dec_inst_valid := Mux(ex_jump_en, false.B, io.inst_bus.ack) 313 | } .otherwise { 314 | dec_inst_valid := false.B 315 | } 316 | 317 | // Opcode extraction and Register Read 318 | 319 | u_cpath.io.inst := Mux(io.inst_bus.ack, dec_inst_data, 0.U) 320 | 321 | u_regs.io.rden0 := true.B 322 | u_regs.io.rdaddr0 := dec_inst_rs1 323 | dec_rdata_op0 := u_regs.io.rddata0 324 | 325 | u_regs.io.rden1 := true.B 326 | u_regs.io.rdaddr1 := dec_inst_rs2 327 | dec_rdata_op1 := u_regs.io.rddata1 328 | 329 | ex_alu_op0 := 0.S 330 | switch(ex_op0_sel) { 331 | is (OP0_RS1) { 332 | // Register Forwarding 333 | when (mem_inst_valid & mem_inst_wb_en & (mem_inst_rd === ex_inst_rs0)) { 334 | ex_alu_op0 := mem_alu_res 335 | } .elsewhen (wb_inst_valid & wb_inst_wb_en & (wb_inst_rd === ex_inst_rs0)) { 336 | ex_alu_op0 := Mux (wb_ctrl_mem_cmd === MCMD_RD, wb_mem_rdval, wb_alu_res) 337 | } .otherwise { 338 | ex_alu_op0 := ex_rdata_op0 339 | } 340 | } 341 | is (OP0_IMU) { ex_alu_op0 := Cat(ex_inst_data(31, 12), Fill(12,0.U)).asSInt } 342 | is (OP0_IMZ) { ex_alu_op0 := Cat(Fill(27,0.U), ex_inst_data(19,15)).asSInt } 343 | } 344 | 345 | ex_alu_op1 := 0.S 346 | switch(ex_op1_sel) { 347 | // Register Forwarding 348 | is (OP1_PC ) { ex_alu_op1 := ex_inst_addr.asSInt } 349 | is (OP1_RS2) { 350 | when (mem_inst_valid & mem_inst_wb_en & (mem_inst_rd === ex_inst_rs1)) { 351 | ex_alu_op1 := mem_alu_res 352 | } .elsewhen (wb_inst_valid & wb_inst_wb_en & (wb_inst_rd === ex_inst_rs1)) { 353 | ex_alu_op1 := Mux (wb_ctrl_mem_cmd === MCMD_RD, wb_mem_rdval, wb_alu_res) 354 | } .elsewhen (ex_csr_wbcsr =/= CSR.X) { 355 | ex_alu_op1 := u_csrfile.io.rw.rdata.asSInt 356 | } .otherwise { 357 | ex_alu_op1 := ex_rdata_op1 358 | } 359 | } 360 | is (OP1_IMI) { ex_alu_op1 := Cat(Fill(20,ex_imm_i(11)), ex_imm_i).asSInt } 361 | is (OP1_IMS) { ex_alu_op1 := Cat(Fill(20,ex_imm_s(11)), ex_imm_s).asSInt } 362 | } 363 | 364 | when (mem_inst_valid & mem_inst_wb_en & (mem_inst_rd === ex_inst_rs1)) { 365 | ex_mem_val := mem_alu_res 366 | } .elsewhen (wb_inst_valid & wb_inst_wb_en & (wb_inst_rd === ex_inst_rs1)) { 367 | ex_mem_val := wb_alu_res 368 | } .otherwise { 369 | ex_mem_val := ex_rdata_op1 370 | } 371 | 372 | // 373 | // ALU Input 374 | // 375 | u_alu.io.func := ex_alu_func 376 | u_alu.io.op0 := ex_alu_op0 377 | u_alu.io.op1 := ex_alu_op1 378 | 379 | io.data_bus.req := mem_ctrl_mem_v 380 | io.data_bus.cmd := mem_ctrl_mem_cmd 381 | io.data_bus.size := mem_ctrl_mem_type 382 | io.data_bus.addr := mem_alu_res.asUInt 383 | io.data_bus.wrdata := mem_mem_val 384 | 385 | // 386 | // WB-Stage Signals 387 | // 388 | u_regs.io.wren := wb_inst_valid & wb_inst_wb_en 389 | u_regs.io.wraddr := wb_inst_rd 390 | when ((wb_jal_en === Y) | (wb_jalr_en === Y)) { 391 | u_regs.io.wrdata := wb_inst_addr.asSInt + 4.S 392 | } .elsewhen (wb_ctrl_mem_cmd === MCMD_RD) { 393 | u_regs.io.wrdata := wb_mem_rdval 394 | } .otherwise { 395 | u_regs.io.wrdata := wb_alu_res 396 | } 397 | 398 | u_mem_sext.io.in_val := io.data_bus.rddata 399 | u_mem_sext.io.ext_type := wb_ctrl_mem_type 400 | wb_mem_rdval := u_mem_sext.io.out_val 401 | 402 | // 403 | // CSR Port 404 | // 405 | u_csrfile.io.rw.cmd := ex_csr_wbcsr 406 | u_csrfile.io.rw.addr := ex_imm_i.asUInt 407 | u_csrfile.io.rw.wdata := ex_alu_op0.asUInt 408 | u_csrfile.io.ecall_inst := ex_ecall_en 409 | 410 | // if (conf.debug == true) { 411 | 412 | val debug_pc_update_cause = Wire(UInt(3.W)) 413 | debug_pc_update_cause := MuxCase (0.U, Array ( 414 | (ex_inst_valid & ex_jalr_en) -> 1.U, 415 | (ex_inst_valid & ex_jal_en) -> 2.U, 416 | (ex_inst_valid & ex_br_jump) -> 3.U, 417 | (ex_inst_valid & ex_mret_en) -> 4.U, 418 | (ex_inst_valid & ex_ecall_en) -> 5.U, 419 | (if_inst_en) -> 6.U 420 | )) 421 | 422 | /* Debug-Port */ 423 | io.dbg_monitor.hart_id := hart_id.U 424 | io.dbg_monitor.valid := io.run 425 | 426 | io.dbg_monitor.inst_fetch_req := io.inst_bus.req 427 | io.dbg_monitor.inst_fetch_addr := io.inst_bus.addr 428 | io.dbg_monitor.inst_fetch_ack := io.inst_bus.ack 429 | io.dbg_monitor.inst_fetch_rddata := io.inst_bus.rddata 430 | 431 | io.dbg_monitor.pc_update_cause := debug_pc_update_cause 432 | 433 | io.dbg_monitor.inst_valid := wb_inst_valid 434 | io.dbg_monitor.inst_addr := wb_inst_addr 435 | io.dbg_monitor.inst_hex := wb_inst_data 436 | 437 | io.dbg_monitor.reg_wren := u_regs.io.wren 438 | io.dbg_monitor.reg_wraddr := u_regs.io.wraddr 439 | io.dbg_monitor.reg_wrdata := u_regs.io.wrdata 440 | 441 | io.dbg_monitor.csr_cmd := ex_csr_wbcsr 442 | io.dbg_monitor.csr_addr := ex_imm_i.asUInt 443 | io.dbg_monitor.csr_wdata := ex_alu_op0.asUInt 444 | 445 | io.dbg_monitor.alu_rdata0 := u_alu.io.op0 446 | io.dbg_monitor.alu_reg_rs0 := Mux(ex_op0_sel === OP0_RS1, ex_inst_rs0, 0.U) 447 | io.dbg_monitor.alu_rdata1 := u_alu.io.op1 448 | io.dbg_monitor.alu_reg_rs1 := Mux(ex_op1_sel === OP1_RS2, ex_inst_rs1, 0.U) 449 | io.dbg_monitor.alu_func := Mux(ex_inst_valid, u_alu.io.func, 0.U) 450 | 451 | io.dbg_monitor.mem_inst_valid := mem_inst_valid & mem_inst_wb_en 452 | io.dbg_monitor.mem_inst_rd := mem_inst_rd 453 | io.dbg_monitor.mem_alu_res := mem_alu_res 454 | 455 | io.dbg_monitor.data_bus_req := io.data_bus.req 456 | io.dbg_monitor.data_bus_cmd := io.data_bus.cmd 457 | io.dbg_monitor.data_bus_addr := io.data_bus.addr 458 | io.dbg_monitor.data_bus_wrdata := io.data_bus.wrdata 459 | io.dbg_monitor.data_bus_ack := io.data_bus.ack 460 | io.dbg_monitor.data_bus_rddata := io.data_bus.rddata 461 | // } 462 | } 463 | 464 | 465 | class SExt [Conf <: RVConfig](conf: Conf) extends Module { 466 | val io = IO (new Bundle { 467 | val in_val = Input(SInt(conf.xlen.W)) 468 | val ext_type = Input(UInt(MT_SIZE)) 469 | 470 | val out_val = Output(SInt(conf.xlen.W)) 471 | }) 472 | 473 | io.out_val := io.in_val 474 | switch (io.ext_type) { 475 | is (MT_B ) { io.out_val := Cat(Fill(conf.xlen-8 , io.in_val( 7)), io.in_val( 7, 0)).asSInt } 476 | is (MT_BU) { io.out_val := Cat(Fill(conf.xlen-8 , 0.U ), io.in_val( 7, 0)).asSInt } 477 | is (MT_H ) { io.out_val := Cat(Fill(conf.xlen-16, io.in_val(15)), io.in_val(15, 0)).asSInt } 478 | is (MT_HU) { io.out_val := Cat(Fill(conf.xlen-16, 0.U ), io.in_val(15, 0)).asSInt } 479 | is (MT_W ) { io.out_val := Cat(Fill(conf.xlen-32, io.in_val(31)), io.in_val(31, 0)).asSInt } 480 | is (MT_WU) { io.out_val := Cat(Fill(conf.xlen-32, 0.U ), io.in_val(31, 0)).asSInt } 481 | is (MT_D ) { io.out_val := io.in_val } 482 | } 483 | } 484 | 485 | 486 | object CpuTop extends App { 487 | chisel3.Driver.execute(args, () => new CpuTop(0, new RV64ISynth)) 488 | } 489 | -------------------------------------------------------------------------------- /src/main/scala/core/cpu_alu.scala: -------------------------------------------------------------------------------- 1 | package cpu 2 | 3 | import chisel3._ 4 | import chisel3.util._ 5 | 6 | import DecodeConsts._ 7 | 8 | class Alu [Conf <: RVConfig](conf: Conf) extends Module { 9 | val io = IO (new Bundle { 10 | val func = Input (UInt(ALU_OP_SIZE)) 11 | val op0 = Input (SInt(conf.xlen.W)) 12 | val op1 = Input (SInt(conf.xlen.W)) 13 | 14 | val res = Output (SInt(conf.xlen.W)) 15 | }) 16 | 17 | // when (io.func =/= ALU_X) { 18 | // printf("ALU : OP1[0x") 19 | // PrintHex(io.i_op0, 16, writer) 20 | // printf("] OP2[0x") 21 | // PrintHex(io.i_op1, 16, writer) 22 | // printf("] %d\n", io.i_func) 23 | // } 24 | 25 | val w_mul_xlen2 = Wire(SInt((conf.xlen*2).W)) 26 | w_mul_xlen2 := 0.S 27 | switch (io.func) { 28 | is (ALU_MUL ) { w_mul_xlen2 := (io.op0.asSInt * io.op1.asSInt).asSInt } 29 | is (ALU_MULH ) { w_mul_xlen2 := (io.op0.asSInt * io.op1.asSInt).asSInt } 30 | is (ALU_MULHSU) { w_mul_xlen2 := (io.op0.asSInt * io.op1.asUInt).asSInt } 31 | is (ALU_MULHU ) { w_mul_xlen2 := (io.op0.asUInt * io.op1.asUInt).asSInt } 32 | } 33 | 34 | val w_mul_xlen = Wire(SInt((conf.xlen).W)) 35 | w_mul_xlen := io.op0(31, 0).asSInt * io.op1(31, 0).asSInt 36 | 37 | val w_res = Wire(SInt(conf.xlen.W)) 38 | w_res := 0.S 39 | switch (io.func) { 40 | is (ALU_ADD ) { w_res := io.op0 + io.op1 } 41 | is (ALU_SUB ) { w_res := io.op0 - io.op1 } 42 | is (ALU_SLL ) { w_res := (io.op0.asUInt << io.op1(5,0).asUInt).asSInt } 43 | is (ALU_SRL ) { w_res := (io.op0.asUInt >> io.op1(5,0).asUInt).asSInt } 44 | is (ALU_SRA ) { w_res := (io.op0 >> io.op1(5,0).asUInt).asSInt } 45 | is (ALU_AND ) { w_res := io.op0 & io.op1 } 46 | is (ALU_OR ) { w_res := io.op0 | io.op1 } 47 | is (ALU_XOR ) { w_res := io.op0 ^ io.op1 } 48 | is (ALU_SLT ) { w_res := Mux(io.op0 < io.op1, 1.S, 0.S) } 49 | is (ALU_SLTU ) { w_res := Mux(io.op0.asUInt < io.op1.asUInt, 1.S, 0.S) } 50 | is (ALU_SNE ) { w_res := Mux(io.op0 =/= io.op1, 1.S, 0.S) } 51 | is (ALU_SEQ ) { w_res := Mux(io.op0 === io.op1, 1.S, 0.S) } 52 | is (ALU_SGE ) { w_res := Mux(io.op0 >= io.op1, 1.S, 0.S) } 53 | is (ALU_SGEU ) { w_res := Mux(io.op0.asUInt >= io.op1.asUInt, 1.S, 0.S) } 54 | is (ALU_COPY1 ) { w_res := io.op0 } 55 | is (ALU_COPY2 ) { w_res := io.op1 } 56 | is (ALU_ADDW ) { w_res := (io.op0(31, 0) + io.op1(31, 0)).asSInt } 57 | is (ALU_SUBW ) { w_res := (io.op0(31, 0) - io.op1(31, 0)).asSInt } 58 | is (ALU_SLLW ) { w_res := ((io.op0(31, 0).asSInt << io.op1(4,0).asUInt)(31, 0)).asSInt } 59 | is (ALU_SRLW ) { w_res := ((io.op0(31, 0).asUInt >> io.op1(4,0).asUInt)(31, 0)).asSInt } 60 | is (ALU_SRAW ) { w_res := ((io.op0(31, 0).asSInt >> io.op1(4,0).asUInt)(31, 0)).asSInt } 61 | is (ALU_MUL ) { w_res := w_mul_xlen2((conf.xlen-1), 0).asSInt } 62 | is (ALU_MULH ) { w_res := w_mul_xlen2((conf.xlen*2-1), conf.xlen).asSInt } 63 | is (ALU_MULHSU) { w_res := w_mul_xlen2((conf.xlen*2-1), conf.xlen).asSInt } 64 | is (ALU_MULHU ) { w_res := w_mul_xlen2((conf.xlen*2-1), conf.xlen).asSInt } 65 | is (ALU_MULW ) { w_res := w_mul_xlen(31, 0).asSInt } 66 | } 67 | 68 | val r_res = Reg(SInt(conf.xlen.W)) 69 | r_res := w_res 70 | io.res := w_res 71 | } 72 | -------------------------------------------------------------------------------- /src/main/scala/core/cpu_bus.scala: -------------------------------------------------------------------------------- 1 | package cpu 2 | 3 | import chisel3._ 4 | import chisel3.util._ 5 | import chisel3.Bool 6 | 7 | import DecodeConsts._ 8 | 9 | class Bus [Conf <: RVConfig](conf: Conf) extends Bundle { 10 | val req = Input(Bool()) 11 | val addr = Input(UInt(conf.bus_width.W)) 12 | val data = Input(SInt(32.W)) 13 | val rddata = Output(SInt(32.W)) 14 | } 15 | 16 | 17 | class InstBus [Conf <: RVConfig](conf: Conf) extends Bundle { 18 | override def cloneType: this.type = 19 | new InstBus(conf).asInstanceOf[this.type] 20 | 21 | val req = Output(Bool()) 22 | val ready = Input(Bool()) 23 | val addr = Output(UInt(conf.bus_width.W)) 24 | 25 | val ack = Input(Bool()) 26 | val rddata = Input(SInt(32.W)) 27 | } 28 | 29 | 30 | class DataBus [Conf <: RVConfig](conf: Conf) extends Bundle { 31 | override def cloneType: this.type = 32 | new DataBus(conf).asInstanceOf[this.type] 33 | 34 | val req = Output(Bool()) 35 | val cmd = Output(UInt(2.W)) 36 | val addr = Output(UInt(conf.bus_width.W)) 37 | val size = Output(UInt(3.W)) 38 | val wrdata = Output(SInt(conf.xlen.W)) 39 | 40 | val ack = Input(Bool()) 41 | val rddata = Input(SInt(64.W)) 42 | } 43 | -------------------------------------------------------------------------------- /src/main/scala/core/cpu_regs.scala: -------------------------------------------------------------------------------- 1 | package cpu 2 | 3 | import chisel3._ 4 | import chisel3.util._ 5 | import chisel3.Bool 6 | 7 | import DecodeConsts._ 8 | 9 | 10 | class RegIo extends Bundle { 11 | val rden0 = Input (Bool()) 12 | val rdaddr0 = Input (UInt(5.W)) 13 | val rddata0 = Output (SInt(64.W)) 14 | 15 | val rden1 = Input (Bool()) 16 | val rdaddr1 = Input (UInt(5.W)) 17 | val rddata1 = Output (SInt(64.W)) 18 | 19 | val wren = Input (Bool()) 20 | val wraddr = Input (UInt(5.W)) 21 | val wrdata = Input (SInt(64.W)) 22 | } 23 | 24 | 25 | class Regs [Conf <: RVConfig](conf: Conf) extends Module { 26 | val io = IO (new RegIo) 27 | 28 | // val r_regs = RegInit( Vec(32, SInt(conf.xlen.W)).asTypeOf(0.U) ) 29 | val r_regs = Mem(32, SInt(conf.xlen.W)) 30 | 31 | when (io.rden0 && (io.rdaddr0 =/= 0.U)) { 32 | io.rddata0 := Mux (io.wren & (io.wraddr === io.rdaddr0), io.wrdata, r_regs(io.rdaddr0)) 33 | } .otherwise { 34 | io.rddata0 := 0.S(conf.xlen.W) 35 | } 36 | 37 | when (io.rden1 && (io.rdaddr1 =/= 0.U)) { 38 | io.rddata1 := Mux (io.wren & (io.wraddr === io.rdaddr1), io.wrdata, r_regs(io.rdaddr1)) 39 | } .otherwise { 40 | io.rddata1 := 0.S(conf.xlen.W) 41 | } 42 | 43 | when (io.wren && (io.wraddr =/= 0.U)) { 44 | r_regs(io.wraddr) := io.wrdata 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/scala/core/csr.scala: -------------------------------------------------------------------------------- 1 | package cpu 2 | 3 | import chisel3._ 4 | import chisel3.util._ 5 | import collection.mutable.LinkedHashMap 6 | import chisel3.Bool 7 | 8 | 9 | object CSR 10 | { 11 | val CSRCMD_SZ = 3.W 12 | val X = 0.U(CSRCMD_SZ) 13 | val Exch = 1.U(CSRCMD_SZ) 14 | val Set = 2.U(CSRCMD_SZ) 15 | val Clear = 3.U(CSRCMD_SZ) 16 | val Inst = 4.U(CSRCMD_SZ) 17 | val Mret = 5.U(CSRCMD_SZ) 18 | } 19 | 20 | 21 | object PRV 22 | { 23 | val U = 0.U(2.W) 24 | val S = 1.U(2.W) 25 | val H = 2.U(2.W) 26 | val M = 3.U(2.W) 27 | } 28 | 29 | 30 | class CsrFileIo [Conf <: RVConfig](conf: Conf) extends Bundle { 31 | val rw = new Bundle { 32 | val cmd = Input(UInt(CSR.CSRCMD_SZ)) 33 | val addr = Input(UInt(12.W)) 34 | val rdata = Output(UInt(conf.xlen.W)) 35 | val wdata = Input(UInt(conf.xlen.W)) 36 | } 37 | val ecall_inst = Input(Bool()) 38 | val mepc = Output(UInt(conf.xlen.W)) 39 | val mtvec = Output(UInt(conf.xlen.W)) 40 | } 41 | 42 | 43 | class MStatus extends Bundle { 44 | // not truly part of mstatus, but convenient 45 | val debug = Bool() 46 | val prv = UInt(2.W) // not truly part of mstatus, but convenient 47 | val sd = Bool() 48 | val zero1 = UInt(8.W) 49 | val tsr = Bool() 50 | val tw = Bool() 51 | val tvm = Bool() 52 | val mxr = Bool() 53 | val sum = Bool() 54 | val mprv = Bool() 55 | val xs = UInt(2.W) 56 | val fs = UInt(2.W) 57 | val mpp = UInt(2.W) 58 | val hpp = UInt(2.W) 59 | val spp = UInt(1.W) 60 | val mpie = Bool() 61 | val hpie = Bool() 62 | val spie = Bool() 63 | val upie = Bool() 64 | val mie = Bool() 65 | val hie = Bool() 66 | val sie = Bool() 67 | val uie = Bool() 68 | } 69 | 70 | 71 | class MIP extends Bundle { 72 | val zero2 = Bool() 73 | val debug = Bool() // keep in sync with CSR.debugIntCause 74 | val zero1 = Bool() 75 | val rocc = Bool() 76 | val meip = Bool() 77 | val heip = Bool() 78 | val seip = Bool() 79 | val ueip = Bool() 80 | val mtip = Bool() 81 | val htip = Bool() 82 | val stip = Bool() 83 | val utip = Bool() 84 | val msip = Bool() 85 | val hsip = Bool() 86 | val ssip = Bool() 87 | val usip = Bool() 88 | } 89 | 90 | 91 | class CsrFile [Conf <: RVConfig](conf: Conf) extends Module 92 | { 93 | val io = IO(new CsrFileIo(conf)) 94 | 95 | val reset_mstatus = WireInit(0.U.asTypeOf(new MStatus())) 96 | reset_mstatus.mpp := PRV.M 97 | reset_mstatus.prv := PRV.M 98 | val reg_mstatus = RegInit(reset_mstatus) 99 | val reg_mepc = Reg(UInt(conf.xlen.W)) 100 | val reg_mcause = Reg(UInt(conf.xlen.W)) 101 | val reg_mtval = Reg(UInt(conf.xlen.W)) 102 | val reg_mscratch = Reg(UInt(conf.xlen.W)) 103 | val reg_mtimecmp = Reg(UInt(conf.xlen.W)) 104 | val reg_medeleg = Reg(UInt(conf.xlen.W)) 105 | 106 | val reg_mip = RegInit(0.U.asTypeOf(new MIP())) 107 | val reg_mie = RegInit(0.U.asTypeOf(new MIP())) 108 | val reg_wfi = RegInit(false.B) 109 | val reg_mtvec = Reg(UInt(conf.xlen.W)) 110 | 111 | // val reg_time = WideCounter(64) 112 | // val reg_instret = WideCounter(64, io.retire) 113 | 114 | val reg_mcounteren = Reg(UInt(32.W)) 115 | //val reg_hpmevent = io.counters.map(c => Reg(init = 0.asUInt(conf.xlen.W))) 116 | //(io.counters zip reg_hpmevent) foreach { case (c, e) => c.eventSel := e } 117 | // val reg_hpmcounter = io.counters.map(c => WideCounter(CSR.hpmWidth, c.inc, reset = false)) 118 | 119 | val new_prv = WireInit(reg_mstatus.prv) 120 | reg_mstatus.prv := new_prv 121 | 122 | val reg_debug = RegInit(false.B) 123 | val reg_dpc = Reg(UInt(conf.xlen.W)) 124 | val reg_dscratch = Reg(UInt(conf.xlen.W)) 125 | val reg_singleStepped = Reg(Bool()) 126 | // val reset_dcsr = WireInit(0.U.asTypeOf(new DCSR())) 127 | // reset_dcsr.xdebugver := 1 128 | // reset_dcsr.prv := PRV.M 129 | // val reg_dcsr = RegInit(reset_dcsr) 130 | 131 | val system_insn = io.rw.cmd === CSR.Inst 132 | val cpu_ren = io.rw.cmd =/= CSR.X && !system_insn 133 | 134 | /* val read_mstatus = io.status.asUInt() */ 135 | val read_mstatus = 0.U 136 | val isa_string = "I" 137 | val misa = BigInt(0) | isa_string.map(x => 1 << (x - 'A')).reduce(_|_) 138 | val impid = 0x8000 // indicates an anonymous source, which can be used 139 | // during development before a Source ID is allocated. 140 | 141 | val read_mapping = collection.mutable.LinkedHashMap[Int,Bits]( 142 | /* CsrAddr.mcycle -> reg_time, */ 143 | /* CsrAddr.minstret -> reg_instret, */ 144 | CsrAddr.mimpid -> 0.U, 145 | CsrAddr.marchid -> 0.U, 146 | CsrAddr.mvendorid -> 0.U, 147 | CsrAddr.misa -> misa.U, 148 | CsrAddr.mimpid -> impid.U, 149 | CsrAddr.mstatus -> read_mstatus, 150 | CsrAddr.mtvec -> reg_mtvec.asUInt(), 151 | CsrAddr.mip -> reg_mip.asUInt(), 152 | CsrAddr.mie -> reg_mie.asUInt(), 153 | CsrAddr.mscratch -> reg_mscratch, 154 | CsrAddr.mepc -> reg_mepc, 155 | CsrAddr.mtval -> reg_mtval, 156 | CsrAddr.mcause -> reg_mcause, 157 | /* CsrAddr.mhartid -> io.hartid, */ 158 | /* CsrAddr.dcsr -> reg_dcsr.asUInt, */ 159 | CsrAddr.dpc -> reg_dpc, 160 | CsrAddr.dscratch -> reg_dscratch, 161 | CsrAddr.medeleg -> reg_medeleg) 162 | 163 | /* 164 | for (i <- 0 until CSR.nCtr) 165 | { 166 | read_mapping += (i + CSR.firstMHPC) -> reg_hpmcounter(i) 167 | read_mapping += (i + CSR.firstMHPCH) -> reg_hpmcounter(i) 168 | } 169 | */ 170 | 171 | /* for (((e, c), i) <- (reg_hpmevent.padTo(CSR.nHPM, 0.U) 172 | zip reg_hpmcounter.map(x => x: UInt).padTo(CSR.nHPM, 0.U)) zipWithIndex) { 173 | read_mapping += (i + CSR.firstHPE) -> e // mhpmeventN 174 | read_mapping += (i + CSR.firstMHPC) -> c // mhpmcounterN 175 | if (conf.usingUser) read_mapping += (i + CSR.firstHPC) -> c // hpmcounterN 176 | if (conf.xprlen == 32) { 177 | read_mapping += (i + CSR.firstMHPCH) -> c // mhpmcounterNh 178 | if (conf.usingUser) read_mapping += (i + CSR.firstHPCH) -> c // hpmcounterNh 179 | } 180 | } 181 | */ 182 | /* 183 | if (conf.usingUser) { 184 | read_mapping += CsrAddr.mcounteren -> reg_mcounteren 185 | read_mapping += CsrAddr.cycle -> reg_time 186 | read_mapping += CsrAddr.instret -> reg_instret 187 | } 188 | */ 189 | /* 190 | if (conf.xprlen == 32) { 191 | read_mapping += CsrAddr.mcycleh -> 0.U //(reg_time >> 32) 192 | read_mapping += CsrAddr.minstreth -> 0.U //(reg_instret >> 32) 193 | if (conf.usingUser) { 194 | read_mapping += CsrAddr.cycleh -> 0.U //(reg_time >> 32) 195 | read_mapping += CsrAddr.instreth -> 0.U //(reg_instret >> 32) 196 | } 197 | } 198 | */ 199 | 200 | val decoded_addr = read_mapping map { case (k, v) => k -> (io.rw.addr === k.U(12.W)) } 201 | 202 | val priv_sufficient = reg_mstatus.prv >= io.rw.addr(9,8) 203 | val read_only = io.rw.addr(11,10).andR 204 | val cpu_wen = cpu_ren && io.rw.cmd =/= CSR.X && priv_sufficient 205 | val wen = cpu_wen && !read_only 206 | val wdata = readModifyWriteCSR(io.rw.cmd, io.rw.rdata, io.rw.wdata) 207 | 208 | val opcode = 1.U << io.rw.addr(2,0) 209 | val insn_call = system_insn && opcode(0) 210 | val insn_break = system_insn && opcode(1) 211 | val insn_ret = system_insn && opcode(2) && priv_sufficient 212 | val insn_wfi = system_insn && opcode(5) && priv_sufficient 213 | 214 | when(io.ecall_inst) { 215 | reg_mcause := Causes.UserEcall.U 216 | } .elsewhen (decoded_addr(CsrAddr.mcause)) { 217 | reg_mcause := wdata & ((BigInt(1) << (63)) + 31).U /* only implement 5 LSBs and MSB */ 218 | } 219 | 220 | io.mepc := reg_mepc 221 | io.mtvec := reg_mtvec 222 | 223 | when (decoded_addr(CsrAddr.dpc)) { reg_dpc := wdata } 224 | when (decoded_addr(CsrAddr.dscratch)) { reg_dscratch := wdata } 225 | 226 | when (decoded_addr(CsrAddr.mepc)) { reg_mepc := (wdata(63,0) >> 2.U) << 2.U } 227 | when (decoded_addr(CsrAddr.mscratch)) { reg_mscratch := wdata } 228 | when (decoded_addr(CsrAddr.mtval)) { reg_mtval := wdata(63,0) } 229 | when (decoded_addr(CsrAddr.mtvec)) { 230 | reg_mtvec := wdata(63,0) 231 | } 232 | when (decoded_addr(CsrAddr.medeleg)) { reg_medeleg := wdata(63,0) } 233 | 234 | private def decodeAny(m: LinkedHashMap[Int,Bits]): Bool = m.map { case(k: Int, _: Bits) => io.rw.addr === k.U(12.W) }.reduce(_||_) 235 | io.rw.rdata := Mux1H(for ((k, v) <- read_mapping) yield decoded_addr(k) -> v) 236 | 237 | def readModifyWriteCSR(cmd: UInt, rdata: UInt, wdata: UInt) = 238 | (Mux((cmd === CSR.Set | cmd === CSR.Clear), rdata, 0.U) | wdata) & ~Mux(cmd === CSR.Clear, wdata, 0.U) 239 | } 240 | -------------------------------------------------------------------------------- /src/main/scala/core/icache.scala: -------------------------------------------------------------------------------- 1 | package cpu 2 | 3 | import chisel3._ 4 | import chisel3.util._ 5 | import chisel3.Bool 6 | 7 | class icache_req_t (val VADDR_WIDTH: Int) extends Bundle 8 | { 9 | val addr = UInt(VADDR_WIDTH.W) 10 | } 11 | class icache_resp_t (val DATA_WIDTH: Int) extends Bundle 12 | { 13 | val data = UInt(DATA_WIDTH.W) 14 | } 15 | class icache_if_t (val VADDR_WIDTH: Int, val DATA_WIDTH: Int) extends Bundle { 16 | val req = Valid(new icache_req_t(VADDR_WIDTH)) 17 | val resp = Flipped(Valid(new icache_resp_t(DATA_WIDTH))) 18 | } 19 | 20 | 21 | class outer_req_t (val VADDR_WIDTH: Int) extends Bundle 22 | { 23 | val addr = UInt(VADDR_WIDTH.W) 24 | } 25 | class outer_resp_t (val DATA_WIDTH: Int) extends Bundle 26 | { 27 | val data = UInt(DATA_WIDTH.W) 28 | } 29 | class outer_if_t (val VADDR_WIDTH: Int, val DATA_WIDTH: Int) extends Bundle { 30 | val req = Valid(new outer_req_t(VADDR_WIDTH)) 31 | val resp = Flipped(Valid(new outer_resp_t(DATA_WIDTH))) 32 | } 33 | 34 | 35 | class icache(val VADDR_WIDTH:Int, val DATA_WIDTH: Int) extends Module 36 | { 37 | val io = IO (new Bundle { 38 | // val ic_req = Flipped(Valid(new icache_req_t(VADDR_WIDTH))) 39 | // val ic_resp = Valid(new icache_resp_t(DATA_WIDTH)) 40 | val ic = Flipped(new icache_if_t(VADDR_WIDTH, DATA_WIDTH)) 41 | val outer = new outer_if_t (VADDR_WIDTH, DATA_WIDTH) 42 | }) 43 | 44 | val UNTAG_WIDTH = 10 45 | val TAG_MSB = VADDR_WIDTH 46 | val TAG_LSB = UNTAG_WIDTH 47 | val TAG_WIDTH = TAG_MSB - TAG_LSB 48 | 49 | // val tag_array = SyncReadMem(Math.pow(2, UNTAG_WIDTH), UInt(TAG_WIDTH.W)) 50 | // val tag_valid = Reg(Vec(Math.pow(2, UNTAG_WIDTH), Bool())) 51 | // val data_array = SeqMem(Math.pow(2, UNTAG_WIDTH), UInt(DATA_WIDTH.W)) 52 | 53 | val tag_array = SyncReadMem(1024, UInt(TAG_WIDTH.W)) 54 | val tag_valid = Reg(Vec(1024, Bool())) 55 | val data_array = SyncReadMem(1024, UInt(DATA_WIDTH.W)) 56 | 57 | val f0_req_addr_untag = io.ic.req.bits.addr(UNTAG_WIDTH-1, 0) 58 | val f0_req_addr_tag = io.ic.req.bits.addr(VADDR_WIDTH-1, UNTAG_WIDTH) 59 | val f1_req_addr_tag = RegNext(f0_req_addr_tag) 60 | 61 | when (RegNext(io.ic.req.valid)) { 62 | when (RegNext(tag_valid(f0_req_addr_tag)) && RegNext(tag_array(f0_req_addr_tag)) === f1_req_addr_tag) { 63 | io.ic.resp.valid := true.B 64 | } .otherwise { 65 | io.ic.resp.valid := false.B 66 | } 67 | } .otherwise { 68 | io.ic.resp.valid := false.B 69 | } 70 | 71 | io.ic.resp.bits.data := data_array.read(f0_req_addr_tag) 72 | 73 | io.outer.req.valid := false.B 74 | io.outer.req.bits.addr := 0.U 75 | 76 | } 77 | 78 | 79 | object icache extends App { 80 | chisel3.Driver.execute(args, () => new icache(48, 64)) 81 | } 82 | -------------------------------------------------------------------------------- /src/main/scala/core/instructions.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package cpu 4 | 5 | import chisel3._ 6 | import chisel3.util._ 7 | 8 | /* Automatically generated by parse-opcodes */ 9 | object Instructions { 10 | def BEQ = BitPat("b?????????????????000?????1100011") 11 | def BNE = BitPat("b?????????????????001?????1100011") 12 | def BLT = BitPat("b?????????????????100?????1100011") 13 | def BGE = BitPat("b?????????????????101?????1100011") 14 | def BLTU = BitPat("b?????????????????110?????1100011") 15 | def BGEU = BitPat("b?????????????????111?????1100011") 16 | def JALR = BitPat("b?????????????????000?????1100111") 17 | def JAL = BitPat("b?????????????????????????1101111") 18 | def LUI = BitPat("b?????????????????????????0110111") 19 | def AUIPC = BitPat("b?????????????????????????0010111") 20 | def ADDI = BitPat("b?????????????????000?????0010011") 21 | def SLLI = BitPat("b000000???????????001?????0010011") 22 | def SLTI = BitPat("b?????????????????010?????0010011") 23 | def SLTIU = BitPat("b?????????????????011?????0010011") 24 | def XORI = BitPat("b?????????????????100?????0010011") 25 | def SRLI = BitPat("b000000???????????101?????0010011") 26 | def SRAI = BitPat("b010000???????????101?????0010011") 27 | def ORI = BitPat("b?????????????????110?????0010011") 28 | def ANDI = BitPat("b?????????????????111?????0010011") 29 | def ADD = BitPat("b0000000??????????000?????0110011") 30 | def SUB = BitPat("b0100000??????????000?????0110011") 31 | def SLL = BitPat("b0000000??????????001?????0110011") 32 | def SLT = BitPat("b0000000??????????010?????0110011") 33 | def SLTU = BitPat("b0000000??????????011?????0110011") 34 | def XOR = BitPat("b0000000??????????100?????0110011") 35 | def SRL = BitPat("b0000000??????????101?????0110011") 36 | def SRA = BitPat("b0100000??????????101?????0110011") 37 | def OR = BitPat("b0000000??????????110?????0110011") 38 | def AND = BitPat("b0000000??????????111?????0110011") 39 | def ADDIW = BitPat("b?????????????????000?????0011011") 40 | def SLLIW = BitPat("b0000000??????????001?????0011011") 41 | def SRLIW = BitPat("b0000000??????????101?????0011011") 42 | def SRAIW = BitPat("b0100000??????????101?????0011011") 43 | def ADDW = BitPat("b0000000??????????000?????0111011") 44 | def SUBW = BitPat("b0100000??????????000?????0111011") 45 | def SLLW = BitPat("b0000000??????????001?????0111011") 46 | def SRLW = BitPat("b0000000??????????101?????0111011") 47 | def SRAW = BitPat("b0100000??????????101?????0111011") 48 | def LB = BitPat("b?????????????????000?????0000011") 49 | def LH = BitPat("b?????????????????001?????0000011") 50 | def LW = BitPat("b?????????????????010?????0000011") 51 | def LD = BitPat("b?????????????????011?????0000011") 52 | def LBU = BitPat("b?????????????????100?????0000011") 53 | def LHU = BitPat("b?????????????????101?????0000011") 54 | def LWU = BitPat("b?????????????????110?????0000011") 55 | def SB = BitPat("b?????????????????000?????0100011") 56 | def SH = BitPat("b?????????????????001?????0100011") 57 | def SW = BitPat("b?????????????????010?????0100011") 58 | def SD = BitPat("b?????????????????011?????0100011") 59 | def FENCE = BitPat("b?????????????????000?????0001111") 60 | def FENCE_I = BitPat("b?????????????????001?????0001111") 61 | def MUL = BitPat("b0000001??????????000?????0110011") 62 | def MULH = BitPat("b0000001??????????001?????0110011") 63 | def MULHSU = BitPat("b0000001??????????010?????0110011") 64 | def MULHU = BitPat("b0000001??????????011?????0110011") 65 | def DIV = BitPat("b0000001??????????100?????0110011") 66 | def DIVU = BitPat("b0000001??????????101?????0110011") 67 | def REM = BitPat("b0000001??????????110?????0110011") 68 | def REMU = BitPat("b0000001??????????111?????0110011") 69 | def MULW = BitPat("b0000001??????????000?????0111011") 70 | def DIVW = BitPat("b0000001??????????100?????0111011") 71 | def DIVUW = BitPat("b0000001??????????101?????0111011") 72 | def REMW = BitPat("b0000001??????????110?????0111011") 73 | def REMUW = BitPat("b0000001??????????111?????0111011") 74 | def LR_W = BitPat("b00010??00000?????010?????0101111") 75 | def SC_W = BitPat("b00011????????????010?????0101111") 76 | def LR_D = BitPat("b00010??00000?????011?????0101111") 77 | def SC_D = BitPat("b00011????????????011?????0101111") 78 | def ECALL = BitPat("b00000000000000000000000001110011") 79 | def EBREAK = BitPat("b00000000000100000000000001110011") 80 | def URET = BitPat("b00000000001000000000000001110011") 81 | def MRET = BitPat("b00110000001000000000000001110011") 82 | def DRET = BitPat("b01111011001000000000000001110011") 83 | def SFENCE_VMA = BitPat("b0001001??????????000000001110011") 84 | def WFI = BitPat("b00010000010100000000000001110011") 85 | def CSRRW = BitPat("b?????????????????001?????1110011") 86 | def CSRRS = BitPat("b?????????????????010?????1110011") 87 | def CSRRC = BitPat("b?????????????????011?????1110011") 88 | def CSRRWI = BitPat("b?????????????????101?????1110011") 89 | def CSRRSI = BitPat("b?????????????????110?????1110011") 90 | def CSRRCI = BitPat("b?????????????????111?????1110011") 91 | def CUSTOM0 = BitPat("b?????????????????000?????0001011") 92 | def CUSTOM0_RS1 = BitPat("b?????????????????010?????0001011") 93 | def CUSTOM0_RS1_RS2 = BitPat("b?????????????????011?????0001011") 94 | def CUSTOM0_RD = BitPat("b?????????????????100?????0001011") 95 | def CUSTOM0_RD_RS1 = BitPat("b?????????????????110?????0001011") 96 | def CUSTOM0_RD_RS1_RS2 = BitPat("b?????????????????111?????0001011") 97 | def CUSTOM1 = BitPat("b?????????????????000?????0101011") 98 | def CUSTOM1_RS1 = BitPat("b?????????????????010?????0101011") 99 | def CUSTOM1_RS1_RS2 = BitPat("b?????????????????011?????0101011") 100 | def CUSTOM1_RD = BitPat("b?????????????????100?????0101011") 101 | def CUSTOM1_RD_RS1 = BitPat("b?????????????????110?????0101011") 102 | def CUSTOM1_RD_RS1_RS2 = BitPat("b?????????????????111?????0101011") 103 | def CUSTOM2 = BitPat("b?????????????????000?????1011011") 104 | def CUSTOM2_RS1 = BitPat("b?????????????????010?????1011011") 105 | def CUSTOM2_RS1_RS2 = BitPat("b?????????????????011?????1011011") 106 | def CUSTOM2_RD = BitPat("b?????????????????100?????1011011") 107 | def CUSTOM2_RD_RS1 = BitPat("b?????????????????110?????1011011") 108 | def CUSTOM2_RD_RS1_RS2 = BitPat("b?????????????????111?????1011011") 109 | def CUSTOM3 = BitPat("b?????????????????000?????1111011") 110 | def CUSTOM3_RS1 = BitPat("b?????????????????010?????1111011") 111 | def CUSTOM3_RS1_RS2 = BitPat("b?????????????????011?????1111011") 112 | def CUSTOM3_RD = BitPat("b?????????????????100?????1111011") 113 | def CUSTOM3_RD_RS1 = BitPat("b?????????????????110?????1111011") 114 | def CUSTOM3_RD_RS1_RS2 = BitPat("b?????????????????111?????1111011") 115 | def SLLI_RV32 = BitPat("b0000000??????????001?????0010011") 116 | def SRLI_RV32 = BitPat("b0000000??????????101?????0010011") 117 | def SRAI_RV32 = BitPat("b0100000??????????101?????0010011") 118 | def RDCYCLE = BitPat("b11000000000000000010?????1110011") 119 | def RDTIME = BitPat("b11000000000100000010?????1110011") 120 | def RDINSTRET = BitPat("b11000000001000000010?????1110011") 121 | def RDCYCLEH = BitPat("b11001000000000000010?????1110011") 122 | def RDTIMEH = BitPat("b11001000000100000010?????1110011") 123 | def RDINSTRETH = BitPat("b11001000001000000010?????1110011") 124 | } 125 | 126 | 127 | object CsrAddr { 128 | val cycle = 0xc00 129 | val instret = 0xc02 130 | val hpmcounter3 = 0xc03 131 | val hpmcounter4 = 0xc04 132 | val hpmcounter5 = 0xc05 133 | val hpmcounter6 = 0xc06 134 | val hpmcounter7 = 0xc07 135 | val hpmcounter8 = 0xc08 136 | val hpmcounter9 = 0xc09 137 | val hpmcounter10 = 0xc0a 138 | val hpmcounter11 = 0xc0b 139 | val hpmcounter12 = 0xc0c 140 | val hpmcounter13 = 0xc0d 141 | val hpmcounter14 = 0xc0e 142 | val hpmcounter15 = 0xc0f 143 | val hpmcounter16 = 0xc10 144 | val hpmcounter17 = 0xc11 145 | val hpmcounter18 = 0xc12 146 | val hpmcounter19 = 0xc13 147 | val hpmcounter20 = 0xc14 148 | val hpmcounter21 = 0xc15 149 | val hpmcounter22 = 0xc16 150 | val hpmcounter23 = 0xc17 151 | val hpmcounter24 = 0xc18 152 | val hpmcounter25 = 0xc19 153 | val hpmcounter26 = 0xc1a 154 | val hpmcounter27 = 0xc1b 155 | val hpmcounter28 = 0xc1c 156 | val hpmcounter29 = 0xc1d 157 | val hpmcounter30 = 0xc1e 158 | val hpmcounter31 = 0xc1f 159 | val mstatus = 0x300 160 | val misa = 0x301 161 | val medeleg = 0x302 162 | val mideleg = 0x303 163 | val mie = 0x304 164 | val mtvec = 0x305 165 | val mscratch = 0x340 166 | val mcounteren = 0x306 167 | val mepc = 0x341 168 | val mcause = 0x342 169 | val mtval = 0x343 170 | val mip = 0x344 171 | val tselect = 0x7a0 172 | val tdata1 = 0x7a1 173 | val tdata2 = 0x7a2 174 | val tdata3 = 0x7a3 175 | val dcsr = 0x7b0 176 | val dpc = 0x7b1 177 | val dscratch = 0x7b2 178 | val mcycle = 0xb00 179 | val minstret = 0xb02 180 | val mhpmcounter3 = 0xb03 181 | val mhpmcounter4 = 0xb04 182 | val mhpmcounter5 = 0xb05 183 | val mhpmcounter6 = 0xb06 184 | val mhpmcounter7 = 0xb07 185 | val mhpmcounter8 = 0xb08 186 | val mhpmcounter9 = 0xb09 187 | val mhpmcounter10 = 0xb0a 188 | val mhpmcounter11 = 0xb0b 189 | val mhpmcounter12 = 0xb0c 190 | val mhpmcounter13 = 0xb0d 191 | val mhpmcounter14 = 0xb0e 192 | val mhpmcounter15 = 0xb0f 193 | val mhpmcounter16 = 0xb10 194 | val mhpmcounter17 = 0xb11 195 | val mhpmcounter18 = 0xb12 196 | val mhpmcounter19 = 0xb13 197 | val mhpmcounter20 = 0xb14 198 | val mhpmcounter21 = 0xb15 199 | val mhpmcounter22 = 0xb16 200 | val mhpmcounter23 = 0xb17 201 | val mhpmcounter24 = 0xb18 202 | val mhpmcounter25 = 0xb19 203 | val mhpmcounter26 = 0xb1a 204 | val mhpmcounter27 = 0xb1b 205 | val mhpmcounter28 = 0xb1c 206 | val mhpmcounter29 = 0xb1d 207 | val mhpmcounter30 = 0xb1e 208 | val mhpmcounter31 = 0xb1f 209 | val mucounteren = 0x320 210 | val mhpmevent3 = 0x323 211 | val mhpmevent4 = 0x324 212 | val mhpmevent5 = 0x325 213 | val mhpmevent6 = 0x326 214 | val mhpmevent7 = 0x327 215 | val mhpmevent8 = 0x328 216 | val mhpmevent9 = 0x329 217 | val mhpmevent10 = 0x32a 218 | val mhpmevent11 = 0x32b 219 | val mhpmevent12 = 0x32c 220 | val mhpmevent13 = 0x32d 221 | val mhpmevent14 = 0x32e 222 | val mhpmevent15 = 0x32f 223 | val mhpmevent16 = 0x330 224 | val mhpmevent17 = 0x331 225 | val mhpmevent18 = 0x332 226 | val mhpmevent19 = 0x333 227 | val mhpmevent20 = 0x334 228 | val mhpmevent21 = 0x335 229 | val mhpmevent22 = 0x336 230 | val mhpmevent23 = 0x337 231 | val mhpmevent24 = 0x338 232 | val mhpmevent25 = 0x339 233 | val mhpmevent26 = 0x33a 234 | val mhpmevent27 = 0x33b 235 | val mhpmevent28 = 0x33c 236 | val mhpmevent29 = 0x33d 237 | val mhpmevent30 = 0x33e 238 | val mhpmevent31 = 0x33f 239 | val mvendorid = 0xf11 240 | val marchid = 0xf12 241 | val mimpid = 0xf13 242 | val mhartid = 0xf14 243 | val cycleh = 0xc80 244 | val instreth = 0xc82 245 | val hpmcounter3h = 0xc83 246 | val hpmcounter4h = 0xc84 247 | val hpmcounter5h = 0xc85 248 | val hpmcounter6h = 0xc86 249 | val hpmcounter7h = 0xc87 250 | val hpmcounter8h = 0xc88 251 | val hpmcounter9h = 0xc89 252 | val hpmcounter10h = 0xc8a 253 | val hpmcounter11h = 0xc8b 254 | val hpmcounter12h = 0xc8c 255 | val hpmcounter13h = 0xc8d 256 | val hpmcounter14h = 0xc8e 257 | val hpmcounter15h = 0xc8f 258 | val hpmcounter16h = 0xc90 259 | val hpmcounter17h = 0xc91 260 | val hpmcounter18h = 0xc92 261 | val hpmcounter19h = 0xc93 262 | val hpmcounter20h = 0xc94 263 | val hpmcounter21h = 0xc95 264 | val hpmcounter22h = 0xc96 265 | val hpmcounter23h = 0xc97 266 | val hpmcounter24h = 0xc98 267 | val hpmcounter25h = 0xc99 268 | val hpmcounter26h = 0xc9a 269 | val hpmcounter27h = 0xc9b 270 | val hpmcounter28h = 0xc9c 271 | val hpmcounter29h = 0xc9d 272 | val hpmcounter30h = 0xc9e 273 | val hpmcounter31h = 0xc9f 274 | val mcycleh = 0xb80 275 | val minstreth = 0xb82 276 | val mhpmcounter3h = 0xb83 277 | val mhpmcounter4h = 0xb84 278 | val mhpmcounter5h = 0xb85 279 | val mhpmcounter6h = 0xb86 280 | val mhpmcounter7h = 0xb87 281 | val mhpmcounter8h = 0xb88 282 | val mhpmcounter9h = 0xb89 283 | val mhpmcounter10h = 0xb8a 284 | val mhpmcounter11h = 0xb8b 285 | val mhpmcounter12h = 0xb8c 286 | val mhpmcounter13h = 0xb8d 287 | val mhpmcounter14h = 0xb8e 288 | val mhpmcounter15h = 0xb8f 289 | val mhpmcounter16h = 0xb90 290 | val mhpmcounter17h = 0xb91 291 | val mhpmcounter18h = 0xb92 292 | val mhpmcounter19h = 0xb93 293 | val mhpmcounter20h = 0xb94 294 | val mhpmcounter21h = 0xb95 295 | val mhpmcounter22h = 0xb96 296 | val mhpmcounter23h = 0xb97 297 | val mhpmcounter24h = 0xb98 298 | val mhpmcounter25h = 0xb99 299 | val mhpmcounter26h = 0xb9a 300 | val mhpmcounter27h = 0xb9b 301 | val mhpmcounter28h = 0xb9c 302 | val mhpmcounter29h = 0xb9d 303 | val mhpmcounter30h = 0xb9e 304 | val mhpmcounter31h = 0xb9f 305 | } 306 | -------------------------------------------------------------------------------- /src/main/scala/core/memory.scala: -------------------------------------------------------------------------------- 1 | package cpu 2 | 3 | import chisel3._ 4 | import chisel3.util._ 5 | import chisel3.Bool 6 | 7 | import BusConsts._ 8 | import DecodeConsts._ 9 | 10 | class MemoryIo [Conf <: RVConfig](conf: Conf) extends Bundle { 11 | val inst_bus = Flipped(new InstBus(conf)) 12 | val data_bus = Flipped(new DataBus(conf)) 13 | 14 | val ext_bus = new Bus(conf) 15 | } 16 | 17 | class CpuMemory [Conf <: RVConfig](conf: Conf) extends Module { 18 | val io = IO(new Bundle { 19 | val mem = new MemoryIo(conf) 20 | }) 21 | 22 | val memory = conf.debug match { 23 | case true => { 24 | val mem_model = Module(new MemoryModel(conf)) 25 | mem_model 26 | } 27 | case _ => { 28 | val mem_model = Module(new MemoryResourceBox(conf)) 29 | mem_model 30 | } 31 | } 32 | 33 | memory.io <> io 34 | } 35 | 36 | class MemoryModel [Conf <: RVConfig](conf: Conf) extends Module { 37 | val io = IO(new Bundle { 38 | val mem = new MemoryIo(conf) 39 | }) 40 | 41 | val inst_rd_data = Wire(Vec(8, UInt(8.W))) 42 | val data_rd_data = Wire(Vec(8, UInt(8.W))) 43 | val ext_rd_data = Wire(Vec(8, UInt(8.W))) 44 | 45 | for (bank <- 0 until 8) { 46 | 47 | val memory = Mem(math.pow(2, conf.bus_width + 2).toInt , UInt(8.W)) 48 | 49 | val bank_idx = bank.U(3.W) 50 | 51 | when (io.mem.ext_bus.req) { 52 | val data_msb = (bank & 0x3)*8+7 53 | val data_lsb = (bank & 0x3)*8+0 54 | when(io.mem.ext_bus.addr(0) === bank_idx(2)) { 55 | // printf("Load Memory : %x <= %x\n", io.mem.ext_bus.addr(conf.bus_width-1, 0), io.mem.ext_bus.data(data_msb, data_lsb)) 56 | memory(io.mem.ext_bus.addr(conf.bus_width-1, 1)) := io.mem.ext_bus.data(data_msb, data_lsb) 57 | } 58 | /* Ext Bus */ 59 | } 60 | ext_rd_data(bank) := memory(io.mem.ext_bus.addr(conf.bus_width-1, 3)) 61 | 62 | /* Inst Bus */ 63 | inst_rd_data(bank) := memory(io.mem.inst_bus.addr(conf.bus_width-1, 3)) 64 | 65 | /* Data Bus */ 66 | data_rd_data(bank) := memory(io.mem.data_bus.addr(conf.bus_width-1, 3)) 67 | // when (io.mem.data_bus.req === true.B && io.mem.data_bus.cmd === MCMD_RD) { 68 | // printf("Load Memory : %x <= %x\n", io.mem.data_bus.addr(conf.bus_width-1, 0), data_rd_data(bank)) 69 | // } 70 | 71 | val data_msb = bank * 8 + 7 72 | val data_lsb = bank * 8 + 0 73 | when(io.mem.data_bus.req & (io.mem.data_bus.cmd === CMD_WR)) { 74 | switch (io.mem.data_bus.size) { 75 | is (MT_D) { 76 | memory(io.mem.data_bus.addr(conf.bus_width-1, 3)) := io.mem.data_bus.wrdata(data_msb, data_lsb) 77 | } 78 | is (MT_W) { 79 | when (io.mem.data_bus.addr(2) === bank_idx(2)) { 80 | memory(io.mem.data_bus.addr(conf.bus_width-1, 3)) := io.mem.data_bus.wrdata((bank & 0x3)*8+7, (bank & 0x3)*8+0) 81 | } 82 | } 83 | is (MT_H) { 84 | when (io.mem.data_bus.addr(2,1) === bank_idx(2,1)) { 85 | memory(io.mem.data_bus.addr(conf.bus_width-1, 3)) := io.mem.data_bus.wrdata((bank & 0x1)*8+7, (bank & 0x1)*8+0) 86 | } 87 | } 88 | is (MT_B) { 89 | when (io.mem.data_bus.addr(2,0) === bank_idx(2,0)) { 90 | memory(io.mem.data_bus.addr(conf.bus_width-1, 3)) := io.mem.data_bus.wrdata(7, 0) 91 | } 92 | } 93 | } 94 | } 95 | } 96 | 97 | val inst_bus_ack = RegNext(io.mem.inst_bus.req) 98 | val inst_bus_rddata = Reg(SInt(64.W)) 99 | 100 | io.mem.inst_bus.ack := inst_bus_ack 101 | io.mem.inst_bus.rddata := inst_bus_rddata 102 | when(io.mem.inst_bus.req & io.mem.inst_bus.addr(2) === 0.U(1.W)) { 103 | inst_bus_rddata := Cat(inst_rd_data(3), inst_rd_data(2), inst_rd_data(1), inst_rd_data(0)).asSInt 104 | } .otherwise { 105 | // printf("PC = %x, data = %x\n", io.mem.inst_bus.addr, Cat(inst_rd_data(7), inst_rd_data(6), inst_rd_data(5), inst_rd_data(4))) 106 | inst_bus_rddata := Cat(inst_rd_data(7), inst_rd_data(6), inst_rd_data(5), inst_rd_data(4)).asSInt 107 | } 108 | 109 | val data_bus_ack = RegNext(io.mem.data_bus.req & (io.mem.data_bus.cmd === CMD_RD)) 110 | val data_bus_rddata = Reg(SInt(64.W)) 111 | 112 | io.mem.data_bus.ack := data_bus_ack 113 | io.mem.data_bus.rddata := data_bus_rddata 114 | switch (io.mem.data_bus.size) { 115 | is(MT_D) { 116 | data_bus_rddata := Cat(data_rd_data(7), data_rd_data(6), data_rd_data(5), data_rd_data(4), 117 | data_rd_data(3), data_rd_data(2), data_rd_data(1), data_rd_data(0)).asSInt 118 | } 119 | is(MT_W) { 120 | data_bus_rddata := Cat(Fill(32, 0.U(1.W)), data_rd_data(io.mem.data_bus.addr(2) * 4.U + 3.U), 121 | data_rd_data(io.mem.data_bus.addr(2) * 4.U + 2.U), 122 | data_rd_data(io.mem.data_bus.addr(2) * 4.U + 1.U), 123 | data_rd_data(io.mem.data_bus.addr(2) * 4.U + 0.U)).asSInt 124 | } 125 | is(MT_WU) { 126 | data_bus_rddata := Cat(Fill(32, 0.U(1.W)), data_rd_data(io.mem.data_bus.addr(2) * 4.U + 3.U), 127 | data_rd_data(io.mem.data_bus.addr(2) * 4.U + 2.U), 128 | data_rd_data(io.mem.data_bus.addr(2) * 4.U + 1.U), 129 | data_rd_data(io.mem.data_bus.addr(2) * 4.U + 0.U)).asSInt 130 | } 131 | is(MT_HU) { 132 | val target_data = Cat(data_rd_data(io.mem.data_bus.addr(2,1) * 2.U + 1.U), data_rd_data(io.mem.data_bus.addr(2,1) * 2.U + 0.U)) 133 | data_bus_rddata := Cat(0.U(48.W), target_data).asSInt 134 | } 135 | is(MT_H ) { 136 | val target_data = Cat(data_rd_data(io.mem.data_bus.addr(2,1) * 2.U + 1.U), data_rd_data(io.mem.data_bus.addr(2,1) * 2.U + 0.U)) 137 | data_bus_rddata := Cat(Fill(48, target_data(15)), target_data).asSInt 138 | } 139 | is(MT_BU) { data_bus_rddata := Cat(Fill(56, 0.U), data_rd_data(io.mem.data_bus.addr(2, 0))).asSInt } 140 | is(MT_B ) { 141 | val target_data = data_rd_data(io.mem.data_bus.addr(2,0)) 142 | data_bus_rddata := Cat(Fill(56, target_data(7)), target_data).asSInt 143 | } 144 | } 145 | 146 | val ext_bus_rddata = Wire(SInt(32.W)) 147 | ext_bus_rddata := Cat (ext_rd_data(io.mem.data_bus.addr(2) * 4.U + 3.U), 148 | ext_rd_data(io.mem.data_bus.addr(2) * 4.U + 2.U), 149 | ext_rd_data(io.mem.data_bus.addr(2) * 4.U + 1.U), 150 | ext_rd_data(io.mem.data_bus.addr(2) * 4.U + 0.U)).asSInt 151 | io.mem.ext_bus.rddata := ext_bus_rddata 152 | 153 | } 154 | -------------------------------------------------------------------------------- /src/main/scala/core/memory_blackbox.scala: -------------------------------------------------------------------------------- 1 | package cpu 2 | 3 | import chisel3._ 4 | import chisel3.util._ 5 | 6 | class MemoryInlineBox [Conf <: RVConfig](conf: Conf) extends Module { 7 | val io = IO(new Bundle { 8 | val mem = new MemoryIo(conf) 9 | }) 10 | 11 | val mem_black_box_core = Module(new MemoryInlineBoxCore(conf)) 12 | 13 | mem_black_box_core.io.clock <> clock 14 | mem_black_box_core.io.mem <> io.mem 15 | } 16 | 17 | 18 | class MemoryInlineBoxCore [Conf <: RVConfig](conf: Conf) extends BlackBox with HasBlackBoxInline { 19 | val io = IO(new Bundle { 20 | val clock = Input(Clock()) 21 | val mem = new MemoryIo(conf) 22 | }) 23 | 24 | setInline("MemoryBlackBoxCore.v", 25 | s""" 26 | |module MemoryBlackBoxCore 27 | | ( 28 | | input logic clock, 29 | | input logic mem_inst_bus_req, 30 | | input logic [15:0] mem_inst_bus_addr, 31 | | output logic mem_inst_bus_ack, 32 | | output logic [31:0] mem_inst_bus_rddata, 33 | | input logic mem_data_bus_req, 34 | | input logic [1:0] mem_data_bus_cmd, 35 | | input logic [15:0] mem_data_bus_addr, 36 | | input logic [2:0] mem_data_bus_size, 37 | | input logic [63:0] mem_data_bus_wrdata, 38 | | output logic [63:0] mem_data_bus_rddata, 39 | | input logic mem_ext_bus_req, 40 | | input logic [15:0] mem_ext_bus_addr, 41 | | input logic [31:0] mem_ext_bus_data, 42 | | output logic [31:0] mem_ext_bus_rddata 43 | | ); 44 | |reg [63: 0] mem[0: 65535]; 45 | | 46 | |always @(posedge clock) begin 47 | | if (mem_data_bus_req & (mem_data_bus_cmd == 1)) begin 48 | | mem[mem_data_bus_addr] <= mem_data_bus_wrdata; 49 | | end 50 | | mem_data_bus_rddata <= mem[mem_data_bus_addr]; 51 | |end 52 | | 53 | |always @(posedge clock) begin 54 | | mem_inst_bus_rddata <= mem[mem_inst_bus_addr]; 55 | |end 56 | | 57 | |always @(posedge clock) begin 58 | | if (mem_ext_bus_req) begin 59 | | mem[mem_extbus_addr] <= mem_ext_bus_data; 60 | | end 61 | |end 62 | | 63 | |assign mem_ext_bus_rddata = mem[mem_extbus_addr]; 64 | | 65 | |endmodule // MemoryBlackBox 66 | """.stripMargin) 67 | } 68 | -------------------------------------------------------------------------------- /src/main/scala/core/memory_resourcebox.scala: -------------------------------------------------------------------------------- 1 | package cpu 2 | 3 | import chisel3._ 4 | import chisel3.util._ 5 | 6 | class MemoryResourceBox [Conf <: RVConfig](conf: Conf) extends Module { 7 | val io = IO(new Bundle { 8 | val mem = new MemoryIo(conf) 9 | }) 10 | 11 | val mem_resource_box_core = Module(new MemoryResourceBoxCore(conf)) 12 | 13 | mem_resource_box_core.io.clock <> clock 14 | mem_resource_box_core.io.mem <> io.mem 15 | } 16 | 17 | class MemoryResourceBoxCore [Conf <: RVConfig](conf: Conf) extends BlackBox with HasBlackBoxResource { 18 | val io = IO(new Bundle { 19 | val clock = Input(Clock()) 20 | val mem = new MemoryIo(conf) 21 | }) 22 | 23 | setResource ("/memory_real.v") 24 | } 25 | -------------------------------------------------------------------------------- /src/main/scala/core_complex/core_complex.scala: -------------------------------------------------------------------------------- 1 | package core_complex 2 | 3 | import chisel3._ 4 | import cpu.{CpuDebugMonitor, RVConfig} 5 | import freechips.rocketchip.config._ 6 | import freechips.rocketchip.tilelink._ 7 | import freechips.rocketchip.diplomacy._ 8 | 9 | class core_complex[Conf <: RVConfig] (conf: Conf, numCores: Int, ramBeatBytes: Int, txns: Int)(implicit p: Parameters) extends LazyModule { 10 | val loader = LazyModule(new loader("loader")) 11 | 12 | // val ifu = LazyModule(new ifu("ifu")) 13 | val core = Seq.tabulate(numCores) { case i => LazyModule(new CoreTop(conf, i, "core" + i.toString)) } 14 | val xbar = LazyModule(new TLXbar) 15 | val memory = LazyModule(new TLRAM(AddressSet(0x80000000L, 0x0ffff), beatBytes = ramBeatBytes)) 16 | 17 | xbar.node := loader.node 18 | core.foreach { case (core) => { 19 | xbar.node := TLDelayer(0.1) := core.inst_node 20 | xbar.node := TLDelayer(0.1) := core.data_node 21 | } 22 | } 23 | memory.node := xbar.node 24 | 25 | lazy val module = new LazyModuleImp(this) { 26 | val io = IO(new Bundle { 27 | val req = Input(Bool()) 28 | val addr = Input(UInt(32.W)) 29 | val data = Input(UInt(32.W)) 30 | val ready = Output(Bool()) 31 | 32 | val cpu_dbg = Output(Vec(numCores, new CpuDebugMonitor(conf))) 33 | }) 34 | 35 | loader.module.io.req := io.req && (io.addr(31,16) =/= 0x2000.U) 36 | loader.module.io.addr := io.addr 37 | loader.module.io.data := io.data 38 | io.ready := loader.module.io.ready 39 | 40 | // CPU Core Contorl 41 | val cpu_run = Seq.fill(numCores) { RegInit(false.B) } 42 | cpu_run.foreach { case(cpu_run) => cpu_run := Mux(io.req && io.req && (io.addr === 0x20000000.U), io.data(0), cpu_run) } 43 | 44 | core.zip(cpu_run).foreach { case (core, cpu_run) => core.module.io.run := cpu_run } 45 | 46 | io.cpu_dbg := core.map { case(core) => core.module.io.dbg_monitor } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/scala/core_complex/generator.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package core_complex 4 | 5 | import java.io.{File, FileWriter} 6 | 7 | import freechips.rocketchip.config.Parameters 8 | import chisel3.Driver 9 | import freechips.rocketchip.util.ElaborationArtefacts 10 | 11 | object Generator { 12 | final def main(args: Array[String]) { 13 | val verilog = Driver.emitVerilog( 14 | new TestHarness()(Parameters.empty) 15 | ) 16 | ElaborationArtefacts.files.foreach { case (extension, contents) => 17 | val f = new File(".", "TestHarness." + extension) 18 | val fw = new FileWriter(f) 19 | fw.write(contents()) 20 | fw.close 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/scala/core_complex/test_harness.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package core_complex 4 | 5 | import chisel3._ 6 | import cpu.RV64IConfig 7 | import freechips.rocketchip.config.Parameters 8 | import freechips.rocketchip.diplomacy.LazyModule 9 | import freechips.rocketchip.util.ElaborationArtefacts 10 | import freechips.rocketchip.tilelink.sim_dtm 11 | 12 | class TestHarness()(implicit p: Parameters) extends Module { 13 | val rv_conf = new RV64IConfig 14 | val numCores = 4 15 | 16 | val io = IO(new Bundle { 17 | val success = Output(Bool()) 18 | }) 19 | 20 | val ldut = LazyModule(new core_complex(rv_conf, numCores = numCores, 4, 5000)) 21 | val dut = Module(ldut.module) 22 | 23 | val dtm = Module(new sim_dtm(rv_conf)); 24 | dtm.io.clock := clock 25 | dtm.io.reset := reset 26 | dut.io.req := dtm.io.req.valid 27 | dut.io.addr := dtm.io.req.bits.addr 28 | dut.io.data := dtm.io.req.bits.data 29 | dtm.io.req.ready := dut.io.ready 30 | 31 | val sim_mon = Seq.fill(numCores) { Module(new sim_monitor(rv_conf)) } 32 | sim_mon.zip(dut.io.cpu_dbg).foreach { case (sim_mon, cpu_dbg) => { 33 | sim_mon.io.clock := clock 34 | sim_mon.io.reset := reset 35 | sim_mon.io.dbg := cpu_dbg 36 | }} 37 | 38 | io.success := false.B 39 | 40 | ElaborationArtefacts.add("graphml", ldut.graphML) 41 | } 42 | -------------------------------------------------------------------------------- /src/main/scala/ifu/ifu.scala: -------------------------------------------------------------------------------- 1 | package freechips.rocketchip.tilelink 2 | 3 | import chisel3._ 4 | 5 | import freechips.rocketchip.config._ 6 | import freechips.rocketchip.amba.ahb._ 7 | import freechips.rocketchip.amba.apb._ 8 | import freechips.rocketchip.amba.axi4._ 9 | import freechips.rocketchip.subsystem.{BaseSubsystemConfig} 10 | import freechips.rocketchip.devices.tilelink._ 11 | import freechips.rocketchip.tilelink._ 12 | import freechips.rocketchip.util._ 13 | import freechips.rocketchip.diplomacy._ 14 | import freechips.rocketchip.diplomaticobjectmodel.logicaltree.{BusMemoryLogicalTreeNode, LogicalModuleTree, LogicalTreeNode} 15 | import freechips.rocketchip.diplomaticobjectmodel.model.{OMECC, TL_UL} 16 | 17 | class ifu(name: String)(implicit p: Parameters) extends LazyModule { 18 | val node = TLClientNode(Seq(TLClientPortParameters(Seq(TLClientParameters(name = name))))) 19 | 20 | lazy val module = new LazyModuleImp(this) { 21 | val io = IO(new Bundle { 22 | val run = Input(Bool()) 23 | val done = Output(Bool()) 24 | val error = Output(Bool()) 25 | }) 26 | 27 | val (out, edge) = node.out(0) 28 | 29 | val baseEnd = 0 30 | val (sizeEnd, sizeOff) = (edge.bundle.sizeBits + baseEnd, baseEnd) 31 | val (sourceEnd, sourceOff) = (edge.bundle.sourceBits + sizeEnd, sizeEnd) 32 | val beatBytes = edge.bundle.dataBits 33 | 34 | val counter = RegInit(0.U((beatBytes * 8).W)) 35 | 36 | val a = out.a 37 | val d = out.d 38 | 39 | val a_addr = RegInit(0.U(edge.bundle.addressBits.W)) 40 | 41 | val req_counter = RegInit(0.U(5.W)) 42 | val ack_counter = RegInit(0.U(5.W)) 43 | val finish = RegInit(false.B) 44 | 45 | when (a.fire()) { 46 | req_counter := req_counter + 1.U 47 | when (req_counter(3, 0).andR) { 48 | a_addr := 0.U 49 | } .otherwise { 50 | a_addr := a_addr + beatBytes.U 51 | } 52 | } 53 | val r_error = Reg(Bool()) 54 | r_error := false.B 55 | io.error := r_error 56 | val answer = 0xdead0000L.U | (ack_counter(3, 0) ## 0.U(5.W)) 57 | dontTouch(answer) 58 | 59 | when (d.fire()) { 60 | ack_counter := ack_counter + 1.U 61 | when(ack_counter(4) && (d.bits.data =/= answer)) { 62 | r_error := true.B 63 | } 64 | } 65 | when (ack_counter.andR && a.fire()) { 66 | finish := true.B 67 | } 68 | 69 | val (_, get_pbits) = edge.Get(0.U , a_addr, 2.U) 70 | val (_, put_pbits) = edge.Put(0.U , a_addr, 2.U, 0xdead0000L.U | a_addr) 71 | a.valid := io.run && !finish 72 | a.bits := Mux(req_counter(4), get_pbits, put_pbits) 73 | 74 | d.ready := true.B 75 | 76 | io.done := finish 77 | 78 | // Tie off unused channels 79 | out.b.valid := false.B 80 | out.c.ready := true.B 81 | out.e.ready := true.B 82 | } 83 | } 84 | 85 | 86 | object ifu 87 | { 88 | def apply(name: String)(implicit p: Parameters): TLInwardNode = 89 | { 90 | val pusher = LazyModule(new ifu(name)) 91 | pusher.node 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/main/scala/tl_unit/TLOriginalSlave.scala: -------------------------------------------------------------------------------- 1 | package freechips.rocketchip.unittest 2 | 3 | import chisel3._ 4 | import freechips.rocketchip.config._ 5 | import freechips.rocketchip.amba.ahb._ 6 | import freechips.rocketchip.amba.apb._ 7 | import freechips.rocketchip.amba.axi4._ 8 | import freechips.rocketchip.subsystem.{BaseSubsystemConfig} 9 | import freechips.rocketchip.devices.tilelink._ 10 | import freechips.rocketchip.tilelink._ 11 | import freechips.rocketchip.util._ 12 | import freechips.rocketchip.diplomacy._ 13 | import freechips.rocketchip.diplomaticobjectmodel.logicaltree.{BusMemoryLogicalTreeNode, LogicalModuleTree, LogicalTreeNode} 14 | import freechips.rocketchip.diplomaticobjectmodel.model.{OMECC, TL_UL} 15 | 16 | 17 | class TLOriginalSlave(ramBeatBytes: Int, txns: Int)(implicit p: Parameters) extends LazyModule { 18 | val pushers = List( 19 | LazyModule(new TLPatternPusher("pat0", Seq( 20 | new WritePattern(0x100, 0x2, 0x012345678L), 21 | new WritePattern(0x500, 0x2, 0x0abcdef01L), 22 | new ReadExpectPattern(0x100, 0x2, 0x012345678L), 23 | new ReadExpectPattern(0x500, 0x2, 0x0abcdef01L) 24 | ))), 25 | LazyModule(new TLPatternPusher("pat1", Seq( 26 | new WritePattern(0x200, 0x2, 0x012345678L), 27 | new WritePattern(0x600, 0x2, 0x0abcdef01L), 28 | new ReadExpectPattern(0x200, 0x2, 0x012345678L), 29 | new ReadExpectPattern(0x600, 0x2, 0x0abcdef01L) 30 | ))), 31 | LazyModule(new TLPatternPusher("pat2", Seq( 32 | new WritePattern(0x300, 0x2, 0x012345678L), 33 | new WritePattern(0x700, 0x2, 0x0abcdef01L), 34 | new ReadExpectPattern(0x300, 0x2, 0x012345678L), 35 | new ReadExpectPattern(0x700, 0x2, 0x0abcdef01L) 36 | ))), 37 | LazyModule(new TLPatternPusher("pat3", Seq( 38 | new WritePattern(0x400, 0x2, 0x012345678L), 39 | new WritePattern(0x800, 0x2, 0x0abcdef01L), 40 | new ReadExpectPattern(0x400, 0x2, 0x012345678L), 41 | new ReadExpectPattern(0x800, 0x2, 0x0abcdef01L) 42 | ))) 43 | ) 44 | val model = List(LazyModule(new TLRAMModel("SRAMSimple")), 45 | LazyModule(new TLRAMModel("SRAMSimple")), 46 | LazyModule(new TLRAMModel("SRAMSimple")), 47 | LazyModule(new TLRAMModel("SRAMSimple"))) 48 | val xbar = LazyModule(new TLXbar) 49 | val slavereg0 = LazyModule(new TLSlaveReg(AddressSet(0x000, 0x3ff), beatBytes = ramBeatBytes)) 50 | val slavereg1 = LazyModule(new TLSlaveReg(AddressSet(0x400, 0x3ff), beatBytes = ramBeatBytes)) 51 | 52 | pushers.zip(model).map{ case (pusher, model) => 53 | xbar.node := model.node := pusher.node 54 | } 55 | slavereg0.node := xbar.node 56 | slavereg1.node := xbar.node 57 | 58 | lazy val module = new LazyModuleImp(this) with UnitTestModule { 59 | // TLPatternPusher 60 | pushers.map(p => p.module.io.run := true.B) 61 | io.finished := pushers.map(p => p.module.io.done).reduce((x, y) => x && y) 62 | } 63 | } 64 | 65 | 66 | class TLOriginalSlaveTest(ramBeatBytes: Int, txns: Int = 5000, timeout: Int = 500000)(implicit p: Parameters) extends UnitTest(timeout) { 67 | val lazy_dut = LazyModule(new TLOriginalSlave(ramBeatBytes, txns)) 68 | val dut = Module(lazy_dut.module) 69 | ElaborationArtefacts.add("graphml", lazy_dut.graphML) 70 | io.finished := dut.io.finished 71 | } 72 | 73 | 74 | class WithTLOriginalSlaveTest extends Config((site, here, up) => { 75 | case UnitTests => (q: Parameters) => { 76 | implicit val p = q 77 | val txns = 1 * site(TestDurationMultiplier) 78 | val timeout = 50000 * site(TestDurationMultiplier) 79 | Seq( 80 | Module(new TLOriginalSlaveTest(4, txns=15*txns, timeout=timeout)) 81 | )} 82 | }) 83 | 84 | class TLOriginalSlaveTestConfig extends Config(new WithTLOriginalSlaveTest ++ new WithTestDuration(1) ++ new BaseSubsystemConfig) 85 | -------------------------------------------------------------------------------- /src/main/scala/tl_unit/TLSlaveReg.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE.SiFive for license details. 2 | 3 | package freechips.rocketchip.tilelink 4 | 5 | import chisel3._ 6 | import chisel3.experimental.chiselName 7 | import freechips.rocketchip.config.Parameters 8 | import freechips.rocketchip.diplomacy._ 9 | import freechips.rocketchip.diplomaticobjectmodel.logicaltree.{BusMemoryLogicalTreeNode, LogicalModuleTree, LogicalTreeNode} 10 | import freechips.rocketchip.diplomaticobjectmodel.model.{OMECC, TL_UL} 11 | import freechips.rocketchip.util._ 12 | import freechips.rocketchip.util.property._ 13 | 14 | class TLSlaveReg( 15 | address: AddressSet, 16 | parentLogicalTreeNode: Option[LogicalTreeNode] = None, 17 | beatBytes: Int = 4, 18 | val devName: Option[String] = None, 19 | val dtsCompat: Option[Seq[String]] = None 20 | )(implicit p: Parameters) extends LazyModule 21 | { 22 | val device = devName 23 | .map(new SimpleDevice(_, dtsCompat.getOrElse(Seq("sifive,sram0")))) 24 | .getOrElse(new MemoryDevice()) 25 | 26 | val node = TLManagerNode(Seq(TLManagerPortParameters( 27 | Seq(TLManagerParameters( 28 | address = List(address), 29 | resources = device.reg("TLSlaveReg"), 30 | regionType = RegionType.IDEMPOTENT, 31 | executable = false, 32 | supportsGet = TransferSizes(1, beatBytes), 33 | supportsPutPartial = TransferSizes(1, beatBytes), 34 | supportsPutFull = TransferSizes(1, beatBytes), 35 | supportsArithmetic = TransferSizes.none, 36 | supportsLogical = TransferSizes.none, 37 | fifoId = Some(0))), // requests are handled in order 38 | beatBytes = beatBytes, 39 | minLatency = 2))) // no bypass needed for this device 40 | 41 | lazy val module = new LazyModuleImp(this) { 42 | val (in, edge) = node.in(0) 43 | 44 | val baseEnd = 0 45 | val (sizeEnd, sizeOff) = (edge.bundle.sizeBits + baseEnd, baseEnd) 46 | val (sourceEnd, sourceOff) = (edge.bundle.sourceBits + sizeEnd, sizeEnd) 47 | 48 | val counter = RegInit(0.U((beatBytes * 8).W)) 49 | 50 | val a = in.a 51 | val d = in.d 52 | 53 | val a_read = a.bits.opcode === TLMessages.Get 54 | val a_write = a.bits.opcode =/= TLMessages.Get 55 | val a_extra = a.bits.source ## a.bits.size 56 | 57 | in.a.ready := true.B 58 | 59 | when (a.fire && a_write) { printf("A.Write Addr = %x, Data = %x", a.bits.address, a.bits.data) } 60 | when (a.fire && a_read ) { printf("A.Read Addr = %x", a.bits.address) } 61 | 62 | when (a_write) { 63 | counter := counter + a.bits.data 64 | } 65 | 66 | d.valid := RegNext(a_read | a_write) 67 | d.bits := edge.AccessAck( 68 | toSource = a_extra(sourceEnd-1, sourceOff), 69 | lgSize = a_extra(sizeEnd-1, sizeOff)) 70 | d.bits.data := counter 71 | d.bits.opcode := Mux(RegNext(a_read), TLMessages.AccessAckData, TLMessages.AccessAck) 72 | 73 | // Tie off unused channels 74 | in.b.valid := false.B 75 | in.c.ready := true.B 76 | in.e.ready := true.B 77 | } 78 | } 79 | 80 | object TLSlaveReg 81 | { 82 | def apply( 83 | address: AddressSet, 84 | parentLogicalTreeNode: Option[LogicalTreeNode] = None, 85 | beatBytes: Int = 4, 86 | devName: Option[String] = None, 87 | )(implicit p: Parameters): TLInwardNode = 88 | { 89 | val ram = LazyModule(new TLSlaveReg(address, parentLogicalTreeNode, beatBytes, devName)) 90 | ram.node 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/main/scala/tl_unit/dtm.scala: -------------------------------------------------------------------------------- 1 | package freechips.rocketchip.tilelink 2 | 3 | import chisel3._ 4 | import chisel3.util.HasBlackBoxResource 5 | import chisel3.util.DecoupledIO 6 | import cpu.{CpuDebugMonitor, RVConfig} 7 | import freechips.rocketchip.config._ 8 | 9 | class debugIO extends Bundle { 10 | val addr = Output(UInt(32.W)) 11 | val data = Output(UInt(32.W)) 12 | } 13 | 14 | class sim_dtm[Conf <: RVConfig](conf: Conf)(implicit p: Parameters) extends BlackBox with HasBlackBoxResource { 15 | val io = IO(new Bundle { 16 | val clock = Input(Clock()) 17 | val reset = Input(Reset()) 18 | val req = DecoupledIO(new debugIO()) 19 | }) 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/scala/tl_unit/sim_monitor.scala: -------------------------------------------------------------------------------- 1 | package core_complex 2 | 3 | import chisel3._ 4 | import chisel3.util.HasBlackBoxResource 5 | import chisel3.util.DecoupledIO 6 | import cpu.{CpuDebugMonitor, RVConfig} 7 | import freechips.rocketchip.config._ 8 | import freechips.rocketchip.tilelink.debugIO 9 | 10 | class sim_monitor[Conf <: RVConfig](conf: Conf)(implicit p: Parameters) extends BlackBox with HasBlackBoxResource { 11 | val io = IO(new Bundle { 12 | val clock = Input(Clock()) 13 | val reset = Input(Reset()) 14 | 15 | val dbg = Input(new CpuDebugMonitor(conf)) 16 | }) 17 | } 18 | -------------------------------------------------------------------------------- /src/main/scala/tl_unit/test_loader.scala: -------------------------------------------------------------------------------- 1 | package core_complex 2 | 3 | import chisel3._ 4 | import chisel3.util._ 5 | 6 | import scala.io.Source 7 | import java.io._ 8 | 9 | import freechips.rocketchip.config._ 10 | import freechips.rocketchip.tilelink._ 11 | import freechips.rocketchip.diplomacy._ 12 | 13 | class loader(name: String)(implicit p: Parameters) extends LazyModule { 14 | val node = TLClientNode(Seq(TLClientPortParameters(Seq(TLClientParameters(name = name))))) 15 | 16 | lazy val module = new LazyModuleImp(this) { 17 | val io = IO(new Bundle { 18 | val req = Input(Bool()) 19 | val addr = Input(UInt(32.W)) 20 | val data = Input(UInt(32.W)) 21 | val ready = Output(Bool()) 22 | }) 23 | 24 | val (out, edge) = node.out(0) 25 | 26 | val baseEnd = 0 27 | val (sizeEnd, sizeOff) = (edge.bundle.sizeBits + baseEnd, baseEnd) 28 | val (sourceEnd, sourceOff) = (edge.bundle.sourceBits + sizeEnd, sizeEnd) 29 | val beatBytes = edge.bundle.dataBits 30 | 31 | val a = out.a 32 | val d = out.d 33 | 34 | d.ready := true.B 35 | 36 | // Tie off unused channels 37 | out.b.valid := false.B 38 | out.c.ready := true.B 39 | out.e.ready := true.B 40 | 41 | val s_init :: s_trans :: Nil = Enum(2) 42 | val trans_state = RegInit(s_init) 43 | 44 | val reg_a_valid = RegInit(false.B) 45 | val reg_a_address = RegNext(io.addr) 46 | val reg_a_data = RegNext(io.data) 47 | 48 | switch (trans_state) { 49 | is (s_init) { 50 | io.ready := true.B 51 | 52 | when(io.req) { 53 | reg_a_valid := true.B 54 | reg_a_address := io.addr 55 | reg_a_data := io.data 56 | io.ready := false.B 57 | 58 | trans_state := s_trans 59 | } 60 | } 61 | is (s_trans) { 62 | when(out.a.fire) { 63 | reg_a_valid := false.B 64 | io.ready := true.B 65 | 66 | trans_state := s_init 67 | } 68 | } 69 | } 70 | out.a.valid := reg_a_valid 71 | out.a.bits.address := reg_a_address 72 | out.a.bits.data := reg_a_data 73 | out.a.bits.opcode := TLMessages.PutFullData 74 | out.a.bits.mask := 0xf.U 75 | out.a.bits.size := 2.U 76 | out.a.bits.param := 0.U 77 | 78 | } 79 | } 80 | 81 | 82 | object loader 83 | { 84 | def apply(name: String)(implicit p: Parameters): TLInwardNode = 85 | { 86 | val module = LazyModule(new loader(name)) 87 | module.node 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /verilator_csrc/main.cpp: -------------------------------------------------------------------------------- 1 | #include "VTestHarness.h" 2 | #include "verilated.h" 3 | // #include "verilated_vcd_c.h" 4 | #include "verilated_fst_c.h" 5 | 6 | static uint64_t trace_count = 0; 7 | bool done_reset; 8 | bool verbose; 9 | 10 | double sc_time_stamp() 11 | { 12 | return trace_count; 13 | } 14 | 15 | int main(int argc, char **argv, char **env) { 16 | Verilated::commandArgs(argc, argv); 17 | VTestHarness* top = new VTestHarness; 18 | 19 | Verilated::traceEverOn(true); 20 | // VerilatedVcdC* tfp = new VerilatedVcdC; 21 | VerilatedFstC* tfp = new VerilatedFstC; 22 | 23 | vluint64_t sim_time = 100000; 24 | 25 | top->trace(tfp, 99); // Trace 99 levels of hierarchy 26 | tfp->open("simx.fst"); 27 | 28 | top->clock = 0; 29 | top->reset = 1; 30 | 31 | while (sc_time_stamp() < sim_time && !top->io_success) { 32 | if (trace_count >= 100) { 33 | top->reset = 0; 34 | } 35 | if ((trace_count % 5) == 0) { 36 | top->clock = !top->clock; 37 | } 38 | 39 | trace_count ++; 40 | top->eval(); 41 | tfp->dump(trace_count); 42 | if ((trace_count % 1000) == 0) { 43 | printf ("Count = %u\n", trace_count); 44 | } 45 | if (done_reset) { 46 | break; 47 | } 48 | } 49 | tfp->close(); 50 | 51 | delete top; 52 | exit(0); 53 | } 54 | -------------------------------------------------------------------------------- /verilator_csrc/verilator.h: -------------------------------------------------------------------------------- 1 | #ifndef _ROCKET_VERILATOR_H 2 | #define _ROCKET_VERILATOR_H 3 | 4 | #include "verilated_vcd_c.h" 5 | #include 6 | #include 7 | 8 | extern bool verbose; 9 | extern bool done_reset; 10 | 11 | class VerilatedVcdFILE : public VerilatedVcdFile { 12 | public: 13 | VerilatedVcdFILE(FILE* file) : file(file) {} 14 | ~VerilatedVcdFILE() {} 15 | bool open(const std::string& name) override { 16 | // file should already be open 17 | return file != NULL; 18 | } 19 | void close() override { 20 | // file should be closed elsewhere 21 | } 22 | ssize_t write(const char* bufp, ssize_t len) override { 23 | return fwrite(bufp, 1, len, file); 24 | } 25 | private: 26 | FILE* file; 27 | }; 28 | 29 | #endif 30 | --------------------------------------------------------------------------------