├── .gitattributes
├── .github
└── workflows
│ ├── difftest-selfhost.yml
│ └── difftest.yml
├── .gitignore
├── .idea
├── .gitignore
├── codeStyles
│ ├── Project.xml
│ └── codeStyleConfig.xml
├── file.template.settings.xml
├── fileTemplates
│ ├── Chisel Bundle.scala
│ ├── Chisel Enum.scala
│ └── Chisel Module.scala
├── inspectionProfiles
│ └── Project_Default.xml
├── modules.xml
└── scala_settings.xml
├── .mill-version
├── .scalafmt.conf
├── .vscode
└── settings.json
├── Makefile
├── README.md
├── build.sc
├── docs
├── chiplab.md
└── design.pdf
├── env.example
├── millw
├── millw.bat
├── scripts
├── modify_verilog.sh
└── refresh_branch.sh
├── src
├── src
│ ├── ComplexCoreCpuTop.scala
│ ├── Elaborate.scala
│ ├── SimpleCoreCpuTop.scala
│ ├── axi
│ │ ├── Arbiter.scala
│ │ ├── Axi3x1Crossbar.scala
│ │ ├── AxiCrossbar.scala
│ │ ├── AxiCrossbarAddr.scala
│ │ ├── AxiCrossbarRead.scala
│ │ ├── AxiCrossbarWrite.scala
│ │ ├── AxiMaster.scala
│ │ ├── AxiRegisterRead.scala
│ │ ├── AxiRegisterWrite.scala
│ │ ├── BetterAxiMaster.scala
│ │ ├── PriorityEncoder.scala
│ │ ├── SetClrReg.scala
│ │ ├── bundles
│ │ │ ├── ArChannel.scala
│ │ │ ├── AwChannel.scala
│ │ │ ├── AxiMasterInterface.scala
│ │ │ ├── BChannel.scala
│ │ │ ├── MasterCrossbar.scala
│ │ │ ├── MasterRead.scala
│ │ │ ├── MasterRegisterRead.scala
│ │ │ ├── MasterRegisterWrite.scala
│ │ │ ├── MasterWrite.scala
│ │ │ ├── RChannel.scala
│ │ │ ├── SlaveCrossbar.scala
│ │ │ ├── SlaveRead.scala
│ │ │ ├── SlaveWrite.scala
│ │ │ └── WChannel.scala
│ │ └── types
│ │ │ └── RegType.scala
│ ├── common
│ │ ├── BaseStage.scala
│ │ ├── CombBaseStage.scala
│ │ ├── DistributedQueue.scala
│ │ ├── DistributedQueuePlus.scala
│ │ ├── LookupQueue.scala
│ │ ├── MultiBaseStage.scala
│ │ ├── MultiQueue.scala
│ │ ├── NoSavedInBaseStage.scala
│ │ ├── NoSavedInMultiBaseStage.scala
│ │ ├── Pc.scala
│ │ ├── RegFile.scala
│ │ ├── SimpleMultiBaseStage.scala
│ │ ├── bundles
│ │ │ ├── AxiMasterPort.scala
│ │ │ ├── BackendRedirectPcNdPort.scala
│ │ │ ├── BaseStagePort.scala
│ │ │ ├── MultiBaseStagePort.scala
│ │ │ ├── PassThroughPort.scala
│ │ │ ├── RfAccessInfoNdPort.scala
│ │ │ ├── RfReadPort.scala
│ │ │ └── RfWriteNdPort.scala
│ │ └── enums
│ │ │ └── ReadWriteSel.scala
│ ├── control
│ │ ├── Csr.scala
│ │ ├── CsrScoreboard.scala
│ │ ├── StableCounter.scala
│ │ ├── bundles
│ │ │ ├── BadVAddrSetBundle.scala
│ │ │ ├── BranchFlushInfo.scala
│ │ │ ├── CsrReadPort.scala
│ │ │ ├── CsrValuePort.scala
│ │ │ ├── CsrWriteNdPort.scala
│ │ │ ├── CuToCsrNdPort.scala
│ │ │ ├── DifftestTimerNdPort.scala
│ │ │ ├── EcodeBundle.scala
│ │ │ ├── LLBitSetBundle.scala
│ │ │ ├── PipelineControlNdPort.scala
│ │ │ └── StableCounterReadPort.scala
│ │ ├── csrRegsBundles
│ │ │ ├── AsidBundle.scala
│ │ │ ├── BadvBundle.scala
│ │ │ ├── CpuidBundle.scala
│ │ │ ├── CrmdBundle.scala
│ │ │ ├── CsrSaveBundle.scala
│ │ │ ├── DmwBundle.scala
│ │ │ ├── EcfgBundle.scala
│ │ │ ├── EentryBundle.scala
│ │ │ ├── EraBundle.scala
│ │ │ ├── EstatBundle.scala
│ │ │ ├── EuenBundle.scala
│ │ │ ├── LlbctlBundle.scala
│ │ │ ├── PgdBundle.scala
│ │ │ ├── PgdhBundle.scala
│ │ │ ├── PgdlBundle.scala
│ │ │ ├── PrmdBundle.scala
│ │ │ ├── TcfgBundle.scala
│ │ │ ├── TiclrBundle.scala
│ │ │ ├── TidBundle.scala
│ │ │ ├── TlbehiBundle.scala
│ │ │ ├── TlbeloBundle.scala
│ │ │ ├── TlbidxBundle.scala
│ │ │ ├── TlbrentryBundle.scala
│ │ │ └── TvalBundle.scala
│ │ └── enums
│ │ │ └── ExceptionPos.scala
│ ├── execution
│ │ ├── Clz.scala
│ │ ├── Div.scala
│ │ ├── Mul.scala
│ │ └── bundles
│ │ │ ├── AluInstNdPort.scala
│ │ │ ├── AluResultNdPort.scala
│ │ │ └── MulDivInstNdPort.scala
│ ├── frontend
│ │ ├── FetchTargetQueue.scala
│ │ ├── Frontend.scala
│ │ ├── InstFetch.scala
│ │ ├── InstFetchStage.scala
│ │ ├── NaiiveFetchStage.scala
│ │ ├── PreDecoder.scala
│ │ ├── SimpleFetchStage.scala
│ │ ├── bpu
│ │ │ ├── BPU.scala
│ │ │ ├── RAS.scala
│ │ │ ├── TagePredictor.scala
│ │ │ ├── bundles
│ │ │ │ ├── BpuFtqMetaNdPort.scala
│ │ │ │ ├── FtqBranchMetaEntry.scala
│ │ │ │ └── TagePredictorUpdateInfoPort.scala
│ │ │ ├── components
│ │ │ │ ├── BasePredictor.scala
│ │ │ │ ├── Bundles
│ │ │ │ │ ├── FtbEntryNdPort.scala
│ │ │ │ │ └── TageMetaPort.scala
│ │ │ │ ├── FTB.scala
│ │ │ │ └── TaggedPreditor.scala
│ │ │ └── utils
│ │ │ │ ├── CsrHash.scala
│ │ │ │ └── DebugCsrHash.scala
│ │ ├── bundles
│ │ │ ├── BpuFtqPort.scala
│ │ │ ├── BranchTakenMetaBundle.scala
│ │ │ ├── CommitFtqTrainNdPort.scala
│ │ │ ├── ExeFtqPort.scala
│ │ │ ├── FetchCsrNdPort.scala
│ │ │ ├── FtqBlockBundle.scala
│ │ │ ├── FtqBpuMetaPort.scala
│ │ │ ├── FtqIFNdPort.scala
│ │ │ ├── ICacheAccessPort.scala
│ │ │ ├── ICacheRequestHandshakePort.scala
│ │ │ ├── ICacheRequestNdPort.scala
│ │ │ ├── InstMemResponseNdPort.scala
│ │ │ └── PredecoderResultNdPort.scala
│ │ └── fetch
│ │ │ ├── InstAddrTransStage.scala
│ │ │ ├── InstPreDecodeStage.scala
│ │ │ ├── InstReqStage.scala
│ │ │ └── InstResStage.scala
│ ├── memory
│ │ ├── BRam.scala
│ │ ├── DCache.scala
│ │ ├── ICache.scala
│ │ ├── LutRam.scala
│ │ ├── SimpleRam.scala
│ │ ├── Tlb.scala
│ │ ├── UncachedAgent.scala
│ │ ├── VBRam.scala
│ │ ├── bundles
│ │ │ ├── CacheMaintenanceControlNdPort.scala
│ │ │ ├── CacheMaintenanceHandshakePort.scala
│ │ │ ├── CacheMaintenanceNdPort.scala
│ │ │ ├── ICacheStatusTagBundle.scala
│ │ │ ├── MemAccessPort.scala
│ │ │ ├── MemRequestHandshakePort.scala
│ │ │ ├── MemResponseNdPort.scala
│ │ │ ├── SimpleRamReadPort.scala
│ │ │ ├── SimpleRamWriteNdPort.scala
│ │ │ ├── StatusTagBundle.scala
│ │ │ ├── TlbCompareEntryBundle.scala
│ │ │ ├── TlbCsrWriteNdPort.scala
│ │ │ ├── TlbEntryBundle.scala
│ │ │ ├── TlbMaintenanceNdPort.scala
│ │ │ ├── TlbTransEntryBundle.scala
│ │ │ ├── TlbTransPort.scala
│ │ │ └── TransExceptionCsrNdPort.scala
│ │ └── enums
│ │ │ ├── DCacheState.scala
│ │ │ ├── ICacheState.scala
│ │ │ ├── TlbInstType.scala
│ │ │ ├── TlbMemType.scala
│ │ │ └── UncachedAgentState.scala
│ ├── pipeline
│ │ ├── common
│ │ │ ├── bundles
│ │ │ │ ├── CacheMaintenanceInstNdPort.scala
│ │ │ │ ├── DifftestLoadNdPort.scala
│ │ │ │ ├── DifftestStoreNdPort.scala
│ │ │ │ ├── DifftestTlbFillNdPort.scala
│ │ │ │ ├── FetchInstInfoBundle.scala
│ │ │ │ ├── FtqInfoBundle.scala
│ │ │ │ ├── InstQueueEnqNdPort.scala
│ │ │ │ ├── MemCsrNdPort.scala
│ │ │ │ ├── MemRequestNdPort.scala
│ │ │ │ ├── PcInstBundle.scala
│ │ │ │ └── RobQueryPcPort.scala
│ │ │ └── enums
│ │ │ │ ├── AddrTransType.scala
│ │ │ │ ├── CacheMaintenanceTargetType.scala
│ │ │ │ ├── MemSizeType.scala
│ │ │ │ ├── RegDataLocateSel.scala
│ │ │ │ ├── RegDataState.scala
│ │ │ │ ├── RobDistributeSel.scala
│ │ │ │ └── RobInstState.scala
│ │ ├── complex
│ │ │ ├── Cu.scala
│ │ │ ├── bundles
│ │ │ │ ├── CommitFtqInfoBundle.scala
│ │ │ │ ├── InstInfoNdPort.scala
│ │ │ │ └── RobInstStoreBundle.scala
│ │ │ ├── commit
│ │ │ │ └── CommitStage.scala
│ │ │ ├── dataforward
│ │ │ │ ├── DataForwardStage.scala
│ │ │ │ └── bundles
│ │ │ │ │ └── ReadPortWithValid.scala
│ │ │ ├── dispatch
│ │ │ │ ├── DispatchStage.scala
│ │ │ │ ├── RenameStage.scala
│ │ │ │ ├── bundles
│ │ │ │ │ ├── IssueInfoWithValidBundle.scala
│ │ │ │ │ ├── PreExeInstNdPort.scala
│ │ │ │ │ ├── RenameRequestNdPort.scala
│ │ │ │ │ ├── RenameResultNdPort.scala
│ │ │ │ │ ├── ReservationStationBundle.scala
│ │ │ │ │ └── ScoreboardChangeNdPort.scala
│ │ │ │ ├── enums
│ │ │ │ │ ├── IssueStageState.scala
│ │ │ │ │ ├── PrfState.scala
│ │ │ │ │ └── ScoreboardState.scala
│ │ │ │ └── rs
│ │ │ │ │ ├── BaseReservationStation.scala
│ │ │ │ │ ├── InOrderReservationStation.scala
│ │ │ │ │ ├── OoOReservationStation.scala
│ │ │ │ │ └── SimpleOoOReservationStation.scala
│ │ │ ├── execution
│ │ │ │ ├── Alu.scala
│ │ │ │ ├── ExePassWbStage.scala
│ │ │ │ └── bundles
│ │ │ │ │ └── JumpBranchInfoNdPort.scala
│ │ │ ├── memory
│ │ │ │ ├── AddrTransStage.scala
│ │ │ │ ├── ExeForMemStage.scala
│ │ │ │ ├── MemReqStage.scala
│ │ │ │ ├── MemResStage.scala
│ │ │ │ └── bundles
│ │ │ │ │ └── StoreInfoBundle.scala
│ │ │ ├── pmu
│ │ │ │ ├── Pmu.scala
│ │ │ │ └── bundles
│ │ │ │ │ ├── PmuBranchMisPredictExeNdPort.scala
│ │ │ │ │ ├── PmuBranchPredictNdPort.scala
│ │ │ │ │ ├── PmuCacheNdPort.scala
│ │ │ │ │ ├── PmuDispatchBundle.scala
│ │ │ │ │ ├── PmuNdPort.scala
│ │ │ │ │ └── PmuStoreQueueNdPort.scala
│ │ │ ├── queue
│ │ │ │ ├── MultiInstQueue.scala
│ │ │ │ ├── bundles
│ │ │ │ │ ├── DecodeOutNdPort.scala
│ │ │ │ │ └── DecodePort.scala
│ │ │ │ └── decode
│ │ │ │ │ ├── Decoder.scala
│ │ │ │ │ ├── Decoder_2R.scala
│ │ │ │ │ ├── Decoder_2RI12.scala
│ │ │ │ │ ├── Decoder_2RI14.scala
│ │ │ │ │ ├── Decoder_2RI16.scala
│ │ │ │ │ ├── Decoder_3R.scala
│ │ │ │ │ ├── Decoder_4R.scala
│ │ │ │ │ └── Decoder_special.scala
│ │ │ └── rob
│ │ │ │ ├── Rob.scala
│ │ │ │ ├── bundles
│ │ │ │ ├── InstWbNdPort.scala
│ │ │ │ ├── RobDistributeBundle.scala
│ │ │ │ ├── RobIdDistributePort.scala
│ │ │ │ ├── RobMatchBundle.scala
│ │ │ │ ├── RobReadRequestNdPort.scala
│ │ │ │ └── RobReadResultNdPort.scala
│ │ │ │ └── lvt
│ │ │ │ ├── LiveValueTable.scala
│ │ │ │ ├── LutRam.scala
│ │ │ │ ├── LvtLastValidTable.scala
│ │ │ │ └── bundles
│ │ │ │ ├── LvtReadPort.scala
│ │ │ │ └── LvtWriteNdPort.scala
│ │ └── simple
│ │ │ ├── AddrTransStage.scala
│ │ │ ├── CommitStage.scala
│ │ │ ├── Cu.scala
│ │ │ ├── MainExeStage.scala
│ │ │ ├── MemReqStage.scala
│ │ │ ├── MemResStage.scala
│ │ │ ├── RegMatchTable.scala
│ │ │ ├── Rob.scala
│ │ │ ├── SimpleExeStage.scala
│ │ │ ├── bundles
│ │ │ ├── CommitFtqInfoBundle.scala
│ │ │ ├── FtqPredictInfoBundle.scala
│ │ │ ├── FtqStoreInfoBundle.scala
│ │ │ ├── InstInfoNdPort.scala
│ │ │ ├── MainExeBranchInfoBundle.scala
│ │ │ ├── PreExeInstNdPort.scala
│ │ │ ├── RSBundle.scala
│ │ │ ├── RegMatchBundle.scala
│ │ │ ├── RegOccupyNdPort.scala
│ │ │ ├── RegReadPort.scala
│ │ │ ├── RegWakeUpNdPort.scala
│ │ │ ├── RobInstStoreBundle.scala
│ │ │ ├── RobRequestPort.scala
│ │ │ └── WbNdPort.scala
│ │ │ ├── decode
│ │ │ ├── BaseDecoder.scala
│ │ │ ├── Decoder_2R.scala
│ │ │ ├── Decoder_2RI12.scala
│ │ │ ├── Decoder_2RI14.scala
│ │ │ ├── Decoder_2RI16.scala
│ │ │ ├── Decoder_3R.scala
│ │ │ ├── Decoder_special.scala
│ │ │ └── bundles
│ │ │ │ ├── DecodeOutNdPort.scala
│ │ │ │ └── DecodePort.scala
│ │ │ ├── execution
│ │ │ └── Alu.scala
│ │ │ ├── id
│ │ │ ├── BaseIssueQueue.scala
│ │ │ ├── CompressIssueQueue.scala
│ │ │ ├── CompressUnit3IssueQueue.scala
│ │ │ ├── DecodeStage.scala
│ │ │ ├── DecodeUnit.scala
│ │ │ ├── IssueQueue.scala
│ │ │ ├── OoOIssueQueue.scala
│ │ │ ├── SimpleInstQueue.scala
│ │ │ ├── Unit3IssueQueue.scala
│ │ │ └── rs
│ │ │ │ ├── IoReservationStation.scala
│ │ │ │ └── OoOReservationStation.scala
│ │ │ └── pmu
│ │ │ ├── Pmu.scala
│ │ │ └── bundles
│ │ │ ├── PmuBranchMisPredictExeNdPort.scala
│ │ │ ├── PmuBranchPredictNdPort.scala
│ │ │ ├── PmuCacheNdPort.scala
│ │ │ └── PmuDispatchInfoBundle.scala
│ ├── spec
│ │ ├── Csr.scala
│ │ ├── ExeInst.scala
│ │ ├── Inst.scala
│ │ ├── Param.scala
│ │ └── package.scala
│ └── utils
│ │ ├── BiCounter.scala
│ │ ├── BiPriorityMux.scala
│ │ ├── MinFinder.scala
│ │ ├── MultiCounter.scala
│ │ └── MultiMux.scala
└── test
│ └── src
│ ├── BaseStageSpec.scala
│ ├── ComponentSpec.scala
│ ├── DCacheMaintenanceSpec.scala
│ ├── DCacheSpec.scala
│ ├── DCacheWritebackSpec.scala
│ ├── DataForwardSpec.scala
│ ├── ExeStageSpecs
│ └── testClz.scala
│ ├── ICacheSpec.scala
│ ├── InstQueueSpec.scala
│ ├── MultiMuxSpec.scala
│ ├── SimpleCpuSpec.scala
│ └── enums
│ └── TestEnum.scala
├── utils
├── firtool
├── firtool.exe
├── firtool_darwin
├── firtool_darwin_x86_64
└── firtool_ubuntu2004
└── verilog
├── arbiter.v
├── axi_3x1_crossbar.v
├── axi_crossbar.v
├── axi_crossbar_addr.v
├── axi_crossbar_rd.v
├── axi_crossbar_wr.v
├── axi_register_rd.v
├── axi_register_wr.v
├── cpu_top.v
├── mycpu_top.v
├── priority_encoder.v
├── simpledual_readfirst_bram.v
├── single_readfirst_bram.v
└── truedual_readfirst_bram.v
/.gitattributes:
--------------------------------------------------------------------------------
1 | firtool text eol=lf
2 | millw text eol=lf
--------------------------------------------------------------------------------
/.github/workflows/difftest-selfhost.yml:
--------------------------------------------------------------------------------
1 | name: Self-hosted Difftest
2 |
3 | on:
4 | push:
5 | branches: [main]
6 | pull_request:
7 | branches: [main]
8 | workflow_dispatch:
9 |
10 | jobs:
11 | rand_test:
12 | runs-on: self-hosted
13 |
14 | steps:
15 | - uses: actions/checkout@v3
16 |
17 | - name: Clone Chiplab Repo
18 | uses: actions/checkout@v3
19 | with:
20 | repository: Invalid-Syntax-NSCSCC/min-chiplab
21 | lfs: true
22 | token: ${{ secrets.DIFFTEST_ACCESS_TOKEN }}
23 | path: chiplab
24 |
25 | - name: Prepare Environment
26 | run: |
27 | echo "`pwd`/chiplab/toolchains/loongarch32r-linux-gnusf-2022-05-20/bin" >> $GITHUB_PATH
28 |
29 | - name: Use Cache
30 | uses: coursier/cache-action@v6
31 |
32 | - name: Elaborate CPU
33 | run: make
34 |
35 | - name: Move to Chiplab
36 | run: |
37 | export CHIPLAB_HOME=`pwd`/chiplab
38 | make chiplab
39 |
40 | - name: Test
41 | run: |
42 | export CHIPLAB_HOME=`pwd`/chiplab
43 | cd ./chiplab/sims/verilator/run_random
44 | make
45 | if [[ -s fail.log || -s nopass.log ]]; then
46 | exit 1
47 | fi
48 |
49 | func_test:
50 | runs-on: self-hosted
51 |
52 | steps:
53 | - uses: actions/checkout@v3
54 |
55 | - name: Clone Chiplab Repo
56 | uses: actions/checkout@v3
57 | with:
58 | repository: Invalid-Syntax-NSCSCC/min-chiplab
59 | lfs: true
60 | token: ${{ secrets.DIFFTEST_ACCESS_TOKEN }}
61 | path: chiplab
62 |
63 | - name: Prepare Environment
64 | run: |
65 | echo "`pwd`/chiplab/toolchains/loongarch32r-linux-gnusf-2022-05-20/bin" >> $GITHUB_PATH
66 |
67 | - name: Use Cache
68 | uses: coursier/cache-action@v6
69 |
70 | - name: Elaborate CPU
71 | run: make
72 |
73 | - name: Move to Chiplab
74 | run: |
75 | export CHIPLAB_HOME=`pwd`/chiplab
76 | make chiplab
77 |
78 | - name: Test
79 | run: |
80 | export CHIPLAB_HOME=`pwd`/chiplab
81 | cd ./chiplab/sims/verilator/run_prog
82 | ./configure.sh --run func/func_lab19 --threads 4 --tail-waveform --tail-simu-trace --waveform-tail-size 200 --trace-tail-size 200
83 | make -j`nproc` > make_log.txt 2>&1
84 | sed -i '/RUN simulation/,$!d' make_log.txt
85 | cat make_log.txt
86 | if ! grep -q 'Reached test end PC' make_log.txt; then
87 | exit 1
88 | fi
89 |
90 | - name: Upload Result
91 | uses: actions/upload-artifact@v3
92 | with:
93 | name: difftest-log
94 | path: |
95 | ./chiplab/sims/verilator/run_prog/make_log.txt
96 | ./chiplab/sims/verilator/run_prog/log/**/simu_trace.*
97 | ./chiplab/sims/verilator/run_prog/obj/**/obj/test.s
98 |
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 |
--------------------------------------------------------------------------------
/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/file.template.settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/fileTemplates/Chisel Bundle.scala:
--------------------------------------------------------------------------------
1 | #if ((${PACKAGE_NAME} && ${PACKAGE_NAME} != ""))package ${PACKAGE_NAME} #end
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import spec._
6 |
7 | class ${NAME} extends Bundle {
8 |
9 | }
--------------------------------------------------------------------------------
/.idea/fileTemplates/Chisel Enum.scala:
--------------------------------------------------------------------------------
1 | #if ((${PACKAGE_NAME} && ${PACKAGE_NAME} != ""))package ${PACKAGE_NAME} #end
2 |
3 | import chisel3.ChiselEnum
4 |
5 | object ${NAME} extends ChiselEnum {
6 | val _dummy = Value
7 | }
--------------------------------------------------------------------------------
/.idea/fileTemplates/Chisel Module.scala:
--------------------------------------------------------------------------------
1 | #if ((${PACKAGE_NAME} && ${PACKAGE_NAME} != ""))package ${PACKAGE_NAME} #end
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import spec._
6 |
7 | class ${NAME} extends Module {
8 | val io = IO(new Bundle {
9 |
10 | })
11 | }
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/scala_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.mill-version:
--------------------------------------------------------------------------------
1 | 0.10.12
--------------------------------------------------------------------------------
/.scalafmt.conf:
--------------------------------------------------------------------------------
1 | version = 3.7.10
2 |
3 | project {
4 | excludePaths = [
5 | "glob:**.v"
6 | ]
7 | }
8 |
9 | runner.dialect = scala213
10 |
11 | maxColumn = 120
12 | align = most
13 | continuationIndent.defnSite = 2
14 | assumeStandardLibraryStripMargin = true
15 | docstrings.style = SpaceAsterisk
16 | lineEndings = preserve
17 | includeCurlyBraceInSelectChains = false
18 | danglingParentheses.preset = true
19 |
20 | align.tokens."+" = [
21 | {
22 | code = ":"
23 | },
24 | {
25 | code = ":="
26 | },
27 | {
28 | code = "="
29 | },
30 | {
31 | code = "<>"
32 | },
33 | {
34 | code = ":<>="
35 | }
36 | ]
37 |
38 | newlines.beforeCurlyLambdaParams = multilineWithCaseOnly
39 | newlines.alwaysBeforeMultilineDef = false
40 | newlines.implicitParamListModifierForce = [before]
41 |
42 | verticalMultiline.atDefnSite = true
43 |
44 | optIn.annotationNewlines = true
45 |
46 | rewrite.rules = [SortImports, PreferCurlyFors, AvoidInfix]
47 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "files.watcherExclude": {
3 | "**/target": true
4 | },
5 | "editor.formatOnSave": true
6 | }
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | BUILD_DIR = ./build
2 |
3 | export PATH := $(abspath ./utils):$(PATH)
4 |
5 | all: clean verilog
6 |
7 | test:
8 | ./millw -i __.test
9 |
10 | verilog:
11 | mkdir -p $(BUILD_DIR)/final
12 | ./millw -i __.test.runMain Elaborate -td $(BUILD_DIR)
13 | cp -f $(BUILD_DIR)/*CoreCpuTop.* $(BUILD_DIR)/final/
14 | cp -f ./verilog/* $(BUILD_DIR)/final/
15 |
16 | chiplab:
17 | rm -rf $${CHIPLAB_HOME}/IP/myCPU/*
18 | cp $(BUILD_DIR)/final/* $${CHIPLAB_HOME}/IP/myCPU
19 |
20 | help:
21 | ./millw -i __.test.runMain Elaborate --help
22 |
23 | compile:
24 | ./millw -i __.compile
25 |
26 | ide:
27 | ./millw -i mill.bsp.BSP/install
28 | ./millw -i --import ivy:com.lihaoyi::mill-contrib-bloop: mill.contrib.bloop.Bloop/install
29 | ./millw -i mill.scalalib.GenIdea/idea
30 |
31 | reformat:
32 | ./millw -i __.reformat
33 |
34 | checkformat:
35 | ./millw -i __.checkFormat
36 |
37 | clean:
38 | rm -rf $(BUILD_DIR)
39 |
40 | .PHONY: test verilog chiplab help compile ide reformat checkformat clean
41 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Invalid CPU
2 |
3 | ## 概述
4 |
5 | Invalid Syntax 参赛队为 NSCSCC 2023 团队赛 LoongArch 赛道设计的 CPU 源代码。
6 |
7 | ## 使用方式
8 |
9 | ### 前置条件
10 |
11 | 请确保在开发系统上配置好 [chiplab](https://gitee.com/loongson-edu/chiplab/tree/chiplab_diff)、IntelliJ IDEA、JDK 等开发工具,并在 IDEA 中安装好 Scala 插件。
12 |
13 | 初次使用 IDEA 打开此项目的时候,需要执行命令 `make ide` 并在 IDEA 中重新加载 BSP 项目。
14 |
15 | *待补充*
16 |
17 | ## 自动化任务
18 |
19 | - `make test`:运行所有测试
20 | - `make verilog`:构建并生成 Verilog 模块
21 | - `scripts/refresh_branch.sh `:将 `` 分支强制同步到远端仓库的 main 分支。建议在每合并一个 PR 之后立即这样做,否则在下次利用此分支提交 PR 时会由于 squash merge 的原因导致引入无关 commits(参见 )
22 |
23 | 其他自动化任务请参考 `Makefile` 和
24 |
25 | ## 分支
26 | + `sub-1`: 初赛提交作品
27 | + `alt-final`: 决赛提交作品
28 | + `custom-final`: NSCSCC 2023 自定义指令翻译代码
29 |
--------------------------------------------------------------------------------
/build.sc:
--------------------------------------------------------------------------------
1 | // import Mill dependency
2 | import mill._
3 | import mill.scalalib._
4 | import mill.scalalib.scalafmt.ScalafmtModule
5 | import mill.scalalib.TestModule.Utest
6 | // support BSP
7 | import mill.bsp._
8 |
9 | object src extends ScalaModule with ScalafmtModule { m =>
10 | override def scalaVersion = "2.13.8"
11 | override def scalacOptions = Seq(
12 | "-language:reflectiveCalls",
13 | "-feature",
14 | "-deprecation",
15 | "-Xcheckinit"
16 | )
17 |
18 | override def ivyDeps = Agg(
19 | ivy"edu.berkeley.cs::chisel3:3.6.0"
20 | )
21 |
22 | override def scalacPluginIvyDeps = Agg(
23 | ivy"edu.berkeley.cs:::chisel3-plugin:3.6.0"
24 | )
25 |
26 | object test extends Tests with Utest {
27 | override def ivyDeps = m.ivyDeps() ++ Agg(
28 | ivy"com.lihaoyi::utest:0.8.1",
29 | ivy"edu.berkeley.cs::chiseltest:0.6.0"
30 | )
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/docs/design.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Invalid-Syntax-NSCSCC/invalid-cpu/0f0110a092bac1ba9d7f5196d5cefd1ef9508d51/docs/design.pdf
--------------------------------------------------------------------------------
/env.example:
--------------------------------------------------------------------------------
1 | export CHIPLAB_HOME=
2 | export PATH=/toolchains//bin:$PATH
--------------------------------------------------------------------------------
/scripts/modify_verilog.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | env LC_ALL=C LANG=C perl -0777 -pe 's/CpuTop/core_top/ ;
4 | s/input[[:space:]]+clock/input aclk/ ;
5 | s/input[[:space:]]+reset/input aresetn/ ;
6 | s/\)\;\n/\)\;\nwire clock;\nassign clock = aclk;\nreg reset;\nalways @(posedge aclk) reset <= ~aresetn;\n/' $1/CpuTop.v > $1/CpuTop_edited.v
--------------------------------------------------------------------------------
/scripts/refresh_branch.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -e
4 |
5 | USAGE=$(cat <
14 |
15 | FLAGS:
16 | -h, --help Prints help information
17 |
18 | ARGS:
19 | The branch to operate
20 | EOF
21 | )
22 |
23 | case $1 in
24 | -h | --help | '' )
25 | echo "$USAGE"
26 | exit
27 | ;;
28 | esac
29 |
30 | echo
31 | while true; do
32 | echo "Do you wish to refresh branch \`$1'? This operation will DISCARD all your unmerged work on branch \`$1' and CANNOT be reverted! (yes/no, default: no)"
33 | read -r yn
34 | case $yn in
35 | [Yy]* )
36 | break
37 | ;;
38 | * )
39 | echo "Operation aborted."
40 | exit
41 | ;;
42 | esac
43 | done
44 |
45 | git switch main
46 | git pull
47 | git branch -D "$1"
48 | git switch -c "$1"
49 | git branch -u origin/"$1" "$1"
50 | git push -f
51 |
--------------------------------------------------------------------------------
/src/src/Elaborate.scala:
--------------------------------------------------------------------------------
1 | import chisel3.stage._
2 | import circt.stage.{CIRCTTarget, CIRCTTargetAnnotation}
3 | import spec.Param
4 |
5 | object Elaborate extends App {
6 |
7 | val generator = if (Param.useSimpleBackend) {
8 | class CoreCpuTop extends SimpleCoreCpuTop
9 | Seq(chisel3.stage.ChiselGeneratorAnnotation(() => new CoreCpuTop))
10 | } else {
11 | class CoreCpuTop extends ComplexCoreCpuTop
12 | Seq(chisel3.stage.ChiselGeneratorAnnotation(() => new CoreCpuTop))
13 | }
14 |
15 | val useMFC = true // Use MLIR-based firrtl compiler
16 |
17 | if (useMFC) {
18 | (new circt.stage.ChiselStage)
19 | .execute(args, generator :+ CIRCTTargetAnnotation(CIRCTTarget.SystemVerilog))
20 | } else {
21 | (new ChiselStage).execute(args, generator)
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/src/axi/AxiCrossbar.scala:
--------------------------------------------------------------------------------
1 | package axi
2 |
3 | import axi.bundles._
4 | import chisel3._
5 | import spec._
6 |
7 | class AxiCrossbar extends Module {
8 | val io = IO(new Bundle {
9 | val slaves = Vec(Param.Count.Axi.slave, new SlaveCrossbar)
10 | val masters = Vec(Param.Count.Axi.master, new MasterCrossbar)
11 | })
12 |
13 | val axiCrossbarWrite = Module(new AxiCrossbarWrite())
14 | for ((src, dst) <- axiCrossbarWrite.io.slaves.zip(io.slaves)) {
15 | src <> dst.write
16 | }
17 | for ((src, dst) <- axiCrossbarWrite.io.masters.zip(io.masters)) {
18 | src <> dst.write
19 | }
20 |
21 | val axiCrossbarRead = Module(new AxiCrossbarRead())
22 | for ((src, dst) <- axiCrossbarRead.io.slaves.zip(io.slaves)) {
23 | src <> dst.read
24 | }
25 | for ((src, dst) <- axiCrossbarRead.io.masters.zip(io.masters)) {
26 | src <> dst.read
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/src/axi/PriorityEncoder.scala:
--------------------------------------------------------------------------------
1 | package axi
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import spec.Param.Axi.Arb._
6 |
7 | class PriorityEncoder(val width: Int) extends Module {
8 | val io = IO(new Bundle {
9 | val inputUnencoded = Input(UInt(width.W))
10 | val outputValid = Output(Bool())
11 | val outputEncoded = Output(UInt(log2Ceil(width).W))
12 | val outputUnencoded = Output(UInt(width.W))
13 | })
14 |
15 | val levels = if (width > 2) log2Ceil(width) else 1
16 | val w = math.pow(2, levels).toInt
17 |
18 | // pad input to even power of two
19 | val inputPadded = Wire(UInt(w.W))
20 | inputPadded := io.inputUnencoded
21 |
22 | val stageValid = Wire(Vec(levels, UInt((w / 2).W)))
23 | val stageEnc = Wire(Vec(levels, UInt((w / 2).W)))
24 |
25 | // porcess input bits; generate valid bit and encoded bit for each pair
26 | val stageValid0 = Wire(Vec(w / 2, Bool()))
27 | val stageEnc0 = Wire(Vec(w / 2, Bool()))
28 | for (n <- 0 until w / 2) {
29 | stageValid0(n) := inputPadded(n * 2 + 1, n * 2).orR
30 | stageEnc0(n) := (if (lsbHighPriority) !inputPadded(n * 2 + 0) else inputPadded(n * 2 + 1))
31 | }
32 | stageValid(0) := stageValid0.asUInt
33 | stageEnc(0) := stageEnc0.asUInt
34 |
35 | // compress down to single valid bit and encoded bus
36 | for (l <- 1 until levels) {
37 | val stageValidl = Wire(Vec(w / 2, Bool()))
38 | val stageEncl = Wire(Vec(w / 2, Bool()))
39 | stageValidl := DontCare
40 | stageEncl := DontCare
41 | for (n <- 0 until w / math.pow(2, l + 1).toInt) {
42 | stageValidl(n) := stageValid(l - 1)(n * 2 + 1, n * 2).asUInt.orR
43 | val data = Mux(
44 | if (lsbHighPriority) stageValid(l - 1)(n * 2 + 0) else !stageValid(l - 1)(n * 2 + 1),
45 | Cat(false.B, stageEnc(l - 1)((n * 2 + 1) * l - 1, (n * 2 + 0) * l)),
46 | Cat(true.B, stageEnc(l - 1)((n * 2 + 2) * l - 1, (n * 2 + 1) * l))
47 | ).asBools
48 | for (k <- 0 until (l + 1))
49 | stageEncl(k + n * (l + 1)) := data(k)
50 | }
51 | stageValid(l) := stageValidl.asUInt
52 | stageEnc(l) := stageEncl.asUInt
53 | }
54 |
55 | io.outputValid := stageValid(levels - 1)(0)
56 | io.outputEncoded := stageEnc(levels - 1)
57 | io.outputUnencoded := 1.U << io.outputEncoded
58 | }
59 |
--------------------------------------------------------------------------------
/src/src/axi/SetClrReg.scala:
--------------------------------------------------------------------------------
1 | package axi
2 |
3 | import chisel3._
4 |
5 | class SetClrReg(val setOverClr: Boolean, val width: Int, val resetValue: Int) extends Module {
6 | val io = IO(new Bundle {
7 | val set = Input(UInt(width.W))
8 | val clr = Input(UInt(width.W))
9 | val result = Output(UInt(width.W))
10 | })
11 |
12 | val resultReg = RegInit(resetValue.U(width.W))
13 | resultReg := (if (setOverClr) {
14 | io.set | (resultReg & (~io.clr).asUInt)
15 | } else {
16 | (io.set | resultReg) & (~io.clr).asUInt
17 | })
18 | io.result := resultReg
19 | }
20 |
--------------------------------------------------------------------------------
/src/src/axi/bundles/ArChannel.scala:
--------------------------------------------------------------------------------
1 | package axi.bundles
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import spec.Param
6 |
7 | class ArChannel
8 | extends DecoupledIO(new Bundle {
9 | val id = UInt(4.W)
10 | val addr = UInt(spec.Width.Axi.addr)
11 | val len = UInt(8.W)
12 | val size = UInt(3.W)
13 | val burst = UInt(2.W)
14 | val lock = Bool()
15 | val cache = UInt(4.W)
16 | val prot = UInt(3.W)
17 | val qos = UInt(4.W)
18 | val region = UInt(4.W)
19 | val user = UInt(Param.Width.Axi.aruser)
20 | })
21 |
--------------------------------------------------------------------------------
/src/src/axi/bundles/AwChannel.scala:
--------------------------------------------------------------------------------
1 | package axi.bundles
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import spec.Param
6 |
7 | class AwChannel
8 | extends DecoupledIO(new Bundle {
9 | val id = UInt(4.W)
10 | val addr = UInt(spec.Width.Axi.addr)
11 | val len = UInt(8.W)
12 | val size = UInt(3.W)
13 | val burst = UInt(2.W)
14 | val lock = Bool()
15 | val cache = UInt(4.W)
16 | val prot = UInt(3.W)
17 | val qos = UInt(4.W)
18 | val region = UInt(4.W)
19 | val user = UInt(Param.Width.Axi.awuser)
20 | })
21 |
--------------------------------------------------------------------------------
/src/src/axi/bundles/AxiMasterInterface.scala:
--------------------------------------------------------------------------------
1 | package axi.bundles
2 |
3 | import chisel3._
4 |
5 | class AxiMasterInterface extends Bundle {
6 | val ar = new ArChannel
7 | val r = Flipped(new RChannel)
8 | val aw = new AwChannel
9 | val w = new WChannel
10 | val b = Flipped(new BChannel)
11 | }
12 |
--------------------------------------------------------------------------------
/src/src/axi/bundles/BChannel.scala:
--------------------------------------------------------------------------------
1 | package axi.bundles
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import spec.Param
6 |
7 | class BChannel
8 | extends DecoupledIO(new Bundle {
9 | val id = UInt(4.W)
10 | val resp = UInt(2.W)
11 | val user = UInt(Param.Width.Axi.buser)
12 | })
13 |
--------------------------------------------------------------------------------
/src/src/axi/bundles/MasterCrossbar.scala:
--------------------------------------------------------------------------------
1 | package axi.bundles
2 |
3 | import chisel3._
4 |
5 | class MasterCrossbar extends Bundle {
6 | val read = new MasterRead
7 | val write = new MasterWrite
8 | }
9 |
--------------------------------------------------------------------------------
/src/src/axi/bundles/MasterRead.scala:
--------------------------------------------------------------------------------
1 | package axi.bundles
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import spec._
6 |
7 | class MasterRead extends Bundle {
8 | val ar = Decoupled(new Bundle {
9 | val id = UInt(Param.Width.Axi.masterId)
10 | val addr = UInt(Width.Axi.addr)
11 | val len = UInt(8.W)
12 | val size = UInt(3.W)
13 | val burst = UInt(2.W)
14 | val lock = Bool()
15 | val cache = UInt(4.W)
16 | val prot = UInt(3.W)
17 | val qos = UInt(4.W)
18 | val region = UInt(4.W)
19 | val user = UInt(Param.Width.Axi.aruser)
20 | })
21 | val r = Flipped(Decoupled(new Bundle {
22 | val id = UInt(Param.Width.Axi.masterId)
23 | val data = UInt(Param.Width.Axi.data)
24 | val resp = UInt(2.W)
25 | val last = Bool()
26 | val user = UInt(Param.Width.Axi.ruser)
27 | }))
28 | }
29 |
--------------------------------------------------------------------------------
/src/src/axi/bundles/MasterRegisterRead.scala:
--------------------------------------------------------------------------------
1 | package axi.bundles
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import spec._
6 |
7 | class MasterRegisterRead(val idWidth: Int) extends Bundle {
8 | val ar = Decoupled(new Bundle {
9 | val id = UInt(idWidth.W)
10 | val addr = UInt(spec.Width.Axi.addr)
11 | val len = UInt(8.W)
12 | val size = UInt(3.W)
13 | val burst = UInt(2.W)
14 | val lock = Bool()
15 | val cache = UInt(4.W)
16 | val prot = UInt(3.W)
17 | val qos = UInt(4.W)
18 | val region = UInt(4.W)
19 | val user = UInt(Param.Width.Axi.aruser)
20 | })
21 | val r = Flipped(Decoupled(new Bundle {
22 | val id = UInt(idWidth.W)
23 | val data = UInt(Param.Width.Axi.data)
24 | val resp = UInt(2.W)
25 | val last = Bool()
26 | val user = UInt(Param.Width.Axi.ruser)
27 | }))
28 | }
29 |
--------------------------------------------------------------------------------
/src/src/axi/bundles/MasterRegisterWrite.scala:
--------------------------------------------------------------------------------
1 | package axi.bundles
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import spec._
6 |
7 | class MasterRegisterWrite(val idWidth: Int) extends Bundle {
8 | val aw = Decoupled(new Bundle {
9 | val id = UInt(idWidth.W)
10 | val addr = UInt(spec.Width.Axi.addr)
11 | val len = UInt(8.W)
12 | val size = UInt(3.W)
13 | val burst = UInt(2.W)
14 | val lock = Bool()
15 | val cache = UInt(4.W)
16 | val prot = UInt(3.W)
17 | val qos = UInt(4.W)
18 | val region = UInt(4.W)
19 | val user = UInt(Param.Width.Axi.awuser)
20 | })
21 | val w = Decoupled(new Bundle {
22 | val data = UInt(Param.Width.Axi.data)
23 | val strb = UInt(Param.Width.Axi.strb)
24 | val last = Bool()
25 | val user = UInt(Param.Width.Axi.wuser)
26 | })
27 | val b = Flipped(Decoupled(new Bundle {
28 | val id = UInt(idWidth.W)
29 | val resp = UInt(2.W)
30 | val user = UInt(Param.Width.Axi.buser)
31 | }))
32 | }
33 |
--------------------------------------------------------------------------------
/src/src/axi/bundles/MasterWrite.scala:
--------------------------------------------------------------------------------
1 | package axi.bundles
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import spec._
6 |
7 | class MasterWrite extends Bundle {
8 | val aw = Decoupled(new Bundle {
9 | val id = UInt(Param.Width.Axi.masterId)
10 | val addr = UInt(spec.Width.Axi.addr)
11 | val len = UInt(8.W)
12 | val size = UInt(3.W)
13 | val burst = UInt(2.W)
14 | val lock = Bool()
15 | val cache = UInt(4.W)
16 | val prot = UInt(3.W)
17 | val qos = UInt(4.W)
18 | val region = UInt(4.W)
19 | val user = UInt(Param.Width.Axi.awuser)
20 | })
21 | val w = Decoupled(new Bundle {
22 | val data = UInt(Param.Width.Axi.data)
23 | val strb = UInt(Param.Width.Axi.strb)
24 | val last = Bool()
25 | val user = UInt(Param.Width.Axi.wuser)
26 | })
27 | val b = Flipped(Decoupled(new Bundle {
28 | val id = UInt(Param.Width.Axi.masterId)
29 | val resp = UInt(2.W)
30 | val user = UInt(Param.Width.Axi.buser)
31 | }))
32 | }
33 |
--------------------------------------------------------------------------------
/src/src/axi/bundles/RChannel.scala:
--------------------------------------------------------------------------------
1 | package axi.bundles
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import spec.Param
6 |
7 | class RChannel
8 | extends DecoupledIO(new Bundle {
9 | val id = UInt(4.W)
10 | val data = UInt(Param.Width.Axi.data)
11 | val resp = UInt(2.W)
12 | val last = Bool()
13 | val user = UInt(Param.Width.Axi.ruser)
14 | })
15 |
--------------------------------------------------------------------------------
/src/src/axi/bundles/SlaveCrossbar.scala:
--------------------------------------------------------------------------------
1 | package axi.bundles
2 |
3 | import chisel3._
4 |
5 | class SlaveCrossbar extends Bundle {
6 | val read = new SlaveRead
7 | val write = new SlaveWrite
8 | }
9 |
--------------------------------------------------------------------------------
/src/src/axi/bundles/SlaveRead.scala:
--------------------------------------------------------------------------------
1 | package axi.bundles
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import spec._
6 |
7 | class SlaveRead extends Bundle {
8 | val ar = Flipped(Decoupled(new Bundle {
9 | val id = UInt(Param.Width.Axi.slaveId)
10 | val addr = UInt(spec.Width.Axi.addr)
11 | val len = UInt(8.W)
12 | val size = UInt(3.W)
13 | val burst = UInt(2.W)
14 | val lock = Bool()
15 | val cache = UInt(4.W)
16 | val prot = UInt(3.W)
17 | val qos = UInt(4.W)
18 | val user = UInt(Param.Width.Axi.aruser)
19 | }))
20 | val r = Decoupled(new Bundle {
21 | val id = UInt(Param.Width.Axi.slaveId)
22 | val data = UInt(Param.Width.Axi.data)
23 | val resp = UInt(2.W)
24 | val last = Bool()
25 | val user = UInt(Param.Width.Axi.ruser)
26 | })
27 | }
28 |
--------------------------------------------------------------------------------
/src/src/axi/bundles/SlaveWrite.scala:
--------------------------------------------------------------------------------
1 | package axi.bundles
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import spec._
6 |
7 | class SlaveWrite extends Bundle {
8 | val aw = Flipped(Decoupled(new Bundle {
9 | val id = UInt(Param.Width.Axi.masterId)
10 | val addr = UInt(spec.Width.Axi.addr)
11 | val len = UInt(8.W)
12 | val size = UInt(3.W)
13 | val burst = UInt(2.W)
14 | val lock = Bool()
15 | val cache = UInt(4.W)
16 | val prot = UInt(3.W)
17 | val qos = UInt(4.W)
18 | val user = UInt(Param.Width.Axi.awuser)
19 | }))
20 | val w = Flipped(Decoupled(new Bundle {
21 | val data = UInt(Param.Width.Axi.data)
22 | val strb = UInt(Param.Width.Axi.strb)
23 | val last = Bool()
24 | val user = UInt(Param.Width.Axi.wuser)
25 | }))
26 | val b = Decoupled(new Bundle {
27 | val id = UInt(Param.Width.Axi.masterId)
28 | val resp = UInt(2.W)
29 | val user = UInt(Param.Width.Axi.buser)
30 | })
31 | }
32 |
--------------------------------------------------------------------------------
/src/src/axi/bundles/WChannel.scala:
--------------------------------------------------------------------------------
1 | package axi.bundles
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import spec.Param
6 |
7 | class WChannel
8 | extends DecoupledIO(new Bundle {
9 | val data = UInt(Param.Width.Axi.data)
10 | val strb = UInt(4.W)
11 | val last = Bool()
12 | val user = UInt(Param.Width.Axi.wuser)
13 | })
14 |
--------------------------------------------------------------------------------
/src/src/axi/types/RegType.scala:
--------------------------------------------------------------------------------
1 | package axi.types
2 |
3 | object RegType extends Enumeration {
4 | type RegType = Value
5 | val BYPASS, SIMPLE_BUFFER, SKID_BUFFER = Value
6 | }
7 |
--------------------------------------------------------------------------------
/src/src/common/CombBaseStage.scala:
--------------------------------------------------------------------------------
1 | package common
2 |
3 | import chisel3._
4 | import common.bundles.BaseStagePort
5 |
6 | abstract class CombBaseStage[InT <: Data, OutT <: Data, PT <: Data](
7 | inNdFactory: => InT,
8 | outNdFactory: => OutT,
9 | blankIn: => InT,
10 | peerFactory: => Option[PT] = None)
11 | extends Module {
12 | val io = IO(new BaseStagePort(inNdFactory, outNdFactory, peerFactory))
13 |
14 | protected val isComputed: Bool = WireDefault(true.B)
15 | protected val isLastComputed: Bool = RegNext(isComputed, true.B)
16 | protected val selectedIn = io.in.bits
17 |
18 | // Handle input
19 | protected val inReady = isLastComputed && io.out.ready
20 | io.in.ready := inReady
21 |
22 | // Handle flush (queue is already handled)
23 | when(io.isFlush) {
24 | io.in.ready := false.B
25 | io.out.valid := false.B
26 | isLastComputed := true.B
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/src/common/DistributedQueue.scala:
--------------------------------------------------------------------------------
1 | package common
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import utils.MultiCounter
6 |
7 | class DistributedQueue[ElemT <: Data](
8 | enqMaxNum: Int,
9 | deqMaxNum: Int,
10 | channelNum: Int,
11 | channelLength: Int,
12 | elemNdFactory: => ElemT,
13 | useSyncReadMem: Boolean = true,
14 | flow: Boolean = false)
15 | extends Module {
16 |
17 | require(channelNum >= enqMaxNum)
18 | require(channelNum >= deqMaxNum)
19 |
20 | val io = IO(new Bundle {
21 | val isFlush = Input(Bool())
22 | val enqueuePorts = Vec(enqMaxNum, Flipped(Decoupled(elemNdFactory)))
23 | val dequeuePorts = Vec(deqMaxNum, Decoupled(elemNdFactory))
24 | })
25 |
26 | // Fallback
27 | io.dequeuePorts.foreach(_ <> DontCare)
28 | io.enqueuePorts.foreach(_.ready := false.B)
29 | io.dequeuePorts.foreach(_.valid := false.B)
30 |
31 | val storeIns = Wire(Vec(channelNum, (DecoupledIO(elemNdFactory))))
32 | val storeOuts = VecInit(storeIns.zipWithIndex.map {
33 | case (in, idx) =>
34 | Queue(
35 | in,
36 | entries = channelLength,
37 | pipe = false,
38 | flow = flow,
39 | useSyncReadMem = useSyncReadMem,
40 | flush = Some(io.isFlush)
41 | )
42 | })
43 |
44 | storeIns.foreach { in =>
45 | in.valid := false.B
46 | in.bits := DontCare
47 | }
48 |
49 | storeOuts.foreach(_.ready := false.B)
50 | if (channelNum == 1) {
51 | // storeOuts(0) <> storeIns(0)
52 | io.enqueuePorts(0) <> storeIns(0)
53 | io.dequeuePorts(0) <> storeOuts(0)
54 | } else {
55 | val enq_ptr = Module(new MultiCounter(channelNum, enqMaxNum))
56 | val deq_ptr = Module(new MultiCounter(channelNum, deqMaxNum))
57 | enq_ptr.io.flush := io.isFlush
58 | deq_ptr.io.flush := io.isFlush
59 |
60 | enq_ptr.io.inc := io.enqueuePorts.zipWithIndex.map {
61 | case (enqPort, idx) =>
62 | // connect
63 | enqPort <> storeIns(enq_ptr.io.incResults(idx))
64 | // return
65 | enqPort.valid && storeIns(enq_ptr.io.incResults(idx)).ready
66 | }.map(_.asUInt).reduce(_ +& _)
67 |
68 | deq_ptr.io.inc := io.dequeuePorts.zipWithIndex.map {
69 | case (deqPort, idx) =>
70 | // connect
71 | deqPort <> storeOuts(deq_ptr.io.incResults(idx))
72 | // return
73 | deqPort.valid && storeOuts(deq_ptr.io.incResults(idx)).ready
74 | }.map(_.asUInt).reduce(_ +& _)
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/src/common/LookupQueue.scala:
--------------------------------------------------------------------------------
1 | package common
2 |
3 | import chisel3._
4 | import chisel3.util._
5 |
6 | class LookupQueue[T <: Data, LUIn <: Data](
7 | val gen: T,
8 | val entries: Int,
9 | val lookupInFactory: LUIn,
10 | val lookupFn: (LUIn, T) => Bool,
11 | val pipe: Boolean = false,
12 | val flow: Boolean = false,
13 | val hasFlush: Boolean = false)
14 | extends Module() {
15 | require(entries > -1, "Queue must have non-negative number of entries")
16 | require(entries != 0, "Use companion object Queue.apply for zero entries")
17 | val genType = gen
18 | val luInType = lookupInFactory
19 |
20 | val io = IO(new Bundle {
21 | val queue = new QueueIO(genType, entries, hasFlush)
22 | val lookup = new Bundle {
23 | val in = Input(luInType)
24 | val out = Output(Bool())
25 | }
26 | })
27 | val ram = Reg(Vec(entries, genType))
28 | val valid_flags = RegInit(VecInit(Seq.fill(entries)(false.B)))
29 | val enq_ptr = Counter(entries)
30 | val deq_ptr = Counter(entries)
31 | val maybe_full = RegInit(false.B)
32 | val ptr_match = enq_ptr.value === deq_ptr.value
33 | val empty = ptr_match && !maybe_full
34 | val full = ptr_match && maybe_full
35 | val do_enq = WireDefault(io.queue.enq.fire)
36 | val do_deq = WireDefault(io.queue.deq.fire)
37 | val flush = io.queue.flush.getOrElse(false.B)
38 |
39 | valid_flags := valid_flags
40 |
41 | // Lookup
42 | val isHit = VecInit(valid_flags.zip(ram).map {
43 | case (valid, entry) =>
44 | valid && lookupFn(io.lookup.in, entry)
45 | }).asUInt.orR
46 | io.lookup.out := isHit
47 |
48 | // when flush is high, empty the queue
49 | // Semantically, any enqueues happen before the flush.
50 | when(do_enq) {
51 | ram(enq_ptr.value) := io.queue.enq.bits
52 | valid_flags(enq_ptr.value) := true.B
53 | enq_ptr.inc()
54 | }
55 | when(do_deq) {
56 | valid_flags(deq_ptr.value) := false.B
57 | deq_ptr.inc()
58 | }
59 | when(do_enq =/= do_deq) {
60 | maybe_full := do_enq
61 | }
62 | when(flush) {
63 | enq_ptr.reset()
64 | deq_ptr.reset()
65 | maybe_full := false.B
66 | valid_flags.foreach(_ := false.B)
67 | }
68 |
69 | io.queue.deq.valid := !empty
70 | io.queue.enq.ready := !full
71 |
72 | io.queue.deq.bits := ram(deq_ptr.value)
73 |
74 | if (flow) {
75 | when(io.queue.enq.valid) { io.queue.deq.valid := true.B }
76 | when(empty) {
77 | io.queue.deq.bits := io.queue.enq.bits
78 | do_deq := false.B
79 | when(io.queue.deq.ready) { do_enq := false.B }
80 | }
81 | }
82 |
83 | if (pipe) {
84 | when(io.queue.deq.ready) { io.queue.enq.ready := true.B }
85 | }
86 |
87 | val ptr_diff = enq_ptr.value - deq_ptr.value
88 |
89 | if (isPow2(entries)) {
90 | io.queue.count := Mux(maybe_full && ptr_match, entries.U, 0.U) | ptr_diff
91 | } else {
92 | io.queue.count := Mux(
93 | ptr_match,
94 | Mux(maybe_full, entries.asUInt, 0.U),
95 | Mux(deq_ptr.value > enq_ptr.value, entries.asUInt + ptr_diff, ptr_diff)
96 | )
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/src/src/common/NoSavedInBaseStage.scala:
--------------------------------------------------------------------------------
1 | package common
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import common.bundles.BaseStagePort
6 |
7 | abstract class NoSavedInBaseStage[InT <: Data, OutT <: Data, PT <: Data](
8 | inNdFactory: => InT,
9 | outNdFactory: => OutT,
10 | blankIn: => InT,
11 | peerFactory: => Option[PT] = None)
12 | extends Module {
13 | val io = IO(new BaseStagePort(inNdFactory, outNdFactory, peerFactory))
14 |
15 | private val queueSize = 1
16 |
17 | protected val resultOutReg: ValidIO[OutT] = RegInit(0.U.asTypeOf(ValidIO(outNdFactory)))
18 | resultOutReg.valid := false.B
19 | private val lastResultOut = Wire(Decoupled(outNdFactory))
20 | lastResultOut.valid := resultOutReg.valid
21 | lastResultOut.bits := resultOutReg.bits
22 | private val outQueue = Queue(
23 | lastResultOut,
24 | entries = queueSize,
25 | pipe = false,
26 | flow = true,
27 | flush = Some(io.isFlush)
28 | )
29 |
30 | // Handle output
31 | io.out <> outQueue
32 |
33 | // Handle input
34 | protected val inReady = (lastResultOut.ready && !lastResultOut.valid) || io.out.ready
35 | io.in.ready := inReady
36 |
37 | // Handle flush (queue is already handled)
38 | when(io.isFlush) {
39 | io.in.ready := false.B
40 | io.out.valid := false.B
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/src/common/NoSavedInMultiBaseStage.scala:
--------------------------------------------------------------------------------
1 | package common
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import common.bundles.MultiBaseStagePort
6 | import spec._
7 |
8 | abstract class NoSavedInMultiBaseStage[InT <: Data, OutT <: Data, PT <: Data](
9 | inNdFactory: => InT,
10 | outNdFactory: => OutT,
11 | blankIn: => InT,
12 | peerFactory: => Option[PT] = None,
13 | inNum: Int = Param.issueInstInfoMaxNum,
14 | outNum: Int = Param.pipelineNum,
15 | outQueueLength: Int = 1,
16 | passOut: Boolean = false)
17 | extends Module {
18 | val io = IO(new MultiBaseStagePort(inNdFactory, outNdFactory, peerFactory, inNum, outNum))
19 |
20 | protected val resultOuts: Vec[ValidIO[OutT]] = WireDefault(
21 | VecInit(Seq.fill(outNum)(0.U.asTypeOf(ValidIO(outNdFactory))))
22 | )
23 |
24 | private val resultOutsReg: Vec[ValidIO[OutT]] = RegInit(
25 | VecInit(Seq.fill(outNum)(0.U.asTypeOf(ValidIO(outNdFactory))))
26 | )
27 | resultOutsReg.zip(resultOuts).foreach { case (dst, src) => dst := src }
28 | protected val lastResultOuts = Wire(Vec(outNum, Decoupled(outNdFactory)))
29 | lastResultOuts.zip(resultOutsReg).foreach {
30 | case (lastResultOut, resultOut) =>
31 | lastResultOut.valid := resultOut.valid
32 | lastResultOut.bits := resultOut.bits
33 | }
34 | private val outQueues = lastResultOuts.map(
35 | Queue(
36 | _,
37 | entries = outQueueLength,
38 | pipe = false,
39 | flow = true,
40 | flush = Some(io.isFlush)
41 | )
42 | )
43 |
44 | protected val selectedIns: Vec[InT] = Wire(Vec(inNum, inNdFactory)) // WireDefault(VecInit(Seq.fill(inNum)(blankIn)))
45 | selectedIns.lazyZip(io.ins).foreach {
46 | case (selectIn, in) => {
47 | selectIn := Mux(
48 | io.isFlush,
49 | blankIn,
50 | Mux(
51 | in.valid,
52 | in.bits,
53 | blankIn
54 | )
55 | )
56 | }
57 | }
58 |
59 | // Handle input
60 | io.ins.foreach(_.ready := false.B)
61 | // 由于in和out不是一一对应,需要处理in.ready
62 | // 模板: io.ins(src).ready := validToIns(dst) && isLastComputeds(src)
63 | protected val validToOuts = Wire(Vec(outNum, Bool()))
64 |
65 | if (passOut) {
66 | io.outs.lazyZip(resultOuts).lazyZip(validToOuts).foreach {
67 | case (out, result, validToOut) =>
68 | validToOut := out.ready
69 | out.valid := result.valid
70 | out.bits := result.bits
71 | }
72 | outQueues.foreach(_ <> DontCare)
73 | } else {
74 | validToOuts.lazyZip(io.outs).lazyZip(lastResultOuts).foreach {
75 | case (v, out, lastResultOut) =>
76 | v := ((lastResultOut.ready && !lastResultOut.valid) || out.ready)
77 | }
78 | // Handle output
79 | io.outs <> outQueues
80 | }
81 |
82 | // Handle flush (queue is already handled)
83 | when(io.isFlush) {
84 | // io.ins.foreach(_.ready := false.B)
85 | // io.outs.foreach(_.valid := false.B)
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/src/common/Pc.scala:
--------------------------------------------------------------------------------
1 | package common
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import common.bundles._
6 | import spec._
7 |
8 | // attention: 从cache不一定能一次性全部取出,待修改
9 | class Pc(
10 | val issueNum: Int = Param.issueInstInfoMaxNum)
11 | extends Module {
12 | val io = IO(new Bundle {
13 | val pc = Output(UInt(Width.Reg.data))
14 | val fetchNum = Input(UInt(log2Ceil(Param.fetchInstMaxNum + 1).W))
15 |
16 | val ftqFull = Input(Bool())
17 | // 异常处理 + 分支跳转
18 | val newPc = Input(new BackendRedirectPcNdPort)
19 |
20 | // bpu pc
21 | val bpuRedirectPc = Input(Valid(UInt(Width.Reg.data)))
22 |
23 | // inst predecode pc
24 | val preDecodePc = Input(Valid(UInt(Width.Reg.data)))
25 | })
26 |
27 | val pcReg = RegInit(spec.Pc.init)
28 | io.pc := pcReg
29 |
30 | // keep pc signal
31 | val ftqFullReg = RegNext(io.ftqFull, false.B)
32 |
33 | // TODO change to fixed fetchNum
34 | // sequential pc
35 | val pcFetchNum = WireDefault(Param.fetchInstMaxNum.U(log2Ceil(Param.fetchInstMaxNum + 1).W))
36 | if (Param.fetchInstMaxNum != 1) {
37 | when(pcReg(Param.Width.ICache._fetchOffset, Param.Width.ICache._instOffset) =/= 0.U) {
38 | pcFetchNum := Param.fetchInstMaxNum.U - pcReg(Param.Width.ICache._fetchOffset - 1, Param.Width.ICache._instOffset)
39 | }
40 | }
41 |
42 | when(io.newPc.en) {
43 | // when predict error or pc error => jump
44 | pcReg := io.newPc.pcAddr
45 | }.elsewhen(io.preDecodePc.valid) {
46 | pcReg := io.preDecodePc.bits
47 | }.elsewhen(io.bpuRedirectPc.valid) {
48 | // bpu reditect when it can predict
49 | pcReg := io.bpuRedirectPc.bits
50 | }.elsewhen(io.ftqFull) {
51 | pcReg := pcReg
52 | }.otherwise {
53 | // sequential pc
54 | pcReg := pcReg + 4.U * io.fetchNum.asUInt
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/src/common/RegFile.scala:
--------------------------------------------------------------------------------
1 | package common
2 |
3 | import chisel3._
4 | import common.bundles._
5 | import spec._
6 |
7 | class RegFile(
8 | issueNum: Int = Param.issueInstInfoMaxNum,
9 | readNum: Int = Param.regFileReadNum,
10 | writeNum: Int = Param.commitNum)
11 | extends Module {
12 | val io = IO(new Bundle {
13 | val writePorts = Input(Vec(writeNum, new RfWriteNdPort))
14 |
15 | val regfileDatas = Output(Vec(Count.reg, UInt(spec.Width.Reg.data)))
16 | })
17 |
18 | // 32 bits registers of 32 number
19 | val regs = RegInit(VecInit(Seq.fill(Count.reg)(zeroWord)))
20 |
21 | // Write
22 | // larger index write first
23 | regs.zipWithIndex.foreach {
24 | case (reg, index) =>
25 | if (index != 0) {
26 | io.writePorts.foreach { write =>
27 | when(write.en && index.U === write.addr) {
28 | reg := write.data
29 | }
30 | }
31 | }
32 | }
33 |
34 | io.regfileDatas.zip(regs).foreach {
35 | case (port, reg) =>
36 | port := reg
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/src/common/SimpleMultiBaseStage.scala:
--------------------------------------------------------------------------------
1 | package common
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import common.bundles.MultiBaseStagePort
6 | import spec._
7 |
8 | abstract class SimpleMultiBaseStage[InT <: Data, OutT <: Data, PT <: Data](
9 | inNdFactory: => InT,
10 | outNdFactory: => OutT,
11 | blankIn: => InT,
12 | peerFactory: => Option[PT] = None,
13 | inNum: Int = Param.issueInstInfoMaxNum,
14 | outNum: Int = Param.pipelineNum)
15 | extends Module {
16 | val io = IO(new MultiBaseStagePort(inNdFactory, outNdFactory, peerFactory, inNum, outNum))
17 |
18 | private val queueSize = 2
19 |
20 | private val outQueue = Module(
21 | new DistributedQueue(
22 | outNum,
23 | outNum,
24 | outNum,
25 | queueSize,
26 | outNdFactory,
27 | useSyncReadMem = false
28 | )
29 | )
30 | outQueue.io.isFlush := io.isFlush
31 |
32 | // Handle output
33 | io.outs.zip(outQueue.io.dequeuePorts).foreach {
34 | case (dst, src) =>
35 | dst <> src
36 | }
37 |
38 | val resultOuts: Vec[DecoupledIO[OutT]] = outQueue.io.enqueuePorts // Vec(outNum, DecoupledIO(outNdFactory))
39 |
40 | // resultOuts.zip(outQueue.io.enqueuePorts).foreach {
41 | // case (src, dst) =>
42 | // dst.valid := src.valid
43 | // dst.
44 | // }
45 |
46 | protected val selectedIns: Vec[InT] = Wire(Vec(inNum, inNdFactory)) // WireDefault(VecInit(Seq.fill(inNum)(blankIn)))
47 | selectedIns.lazyZip(io.ins).foreach {
48 | case (selectIn, in) => {
49 | selectIn := Mux(
50 | // io.isFlush,
51 | // blankIn,
52 | // Mux(
53 | in.valid,
54 | in.bits,
55 | blankIn
56 | )
57 | // )
58 | }
59 | }
60 |
61 | // // Handle input
62 | // io.ins.foreach(_.ready := false.B)
63 | // // 由于in和out不是一一对应,需要处理in.ready
64 | // // 模板: io.ins(src).ready := validToIns(dst) && isLastComputeds(src)
65 | // protected val validToOuts = Wire(Vec(outNum, Bool()))
66 | // validToOuts.lazyZip(io.outs).lazyZip(lastResultOuts).foreach {
67 | // case (v, out, lastResultOut) =>
68 | // v := ((lastResultOut.ready && !lastResultOut.valid) || out.ready)
69 | // }
70 |
71 | // Handle flush (queue is already handled)
72 | when(io.isFlush) {
73 | io.ins.foreach(_.ready := false.B)
74 | io.outs.foreach(_.valid := false.B)
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/src/common/bundles/AxiMasterPort.scala:
--------------------------------------------------------------------------------
1 | package common.bundles
2 |
3 | import chisel3._
4 | import spec._
5 |
6 | class AxiMasterPort extends Bundle {
7 | // Read request
8 | val arid = Output(UInt(4.W))
9 | val araddr = Output(UInt(spec.Width.Axi.addr))
10 | val arlen = Output(UInt(8.W))
11 | val arsize = Output(UInt(3.W))
12 | val arburst = Output(UInt(2.W))
13 | val arlock = Output(UInt(2.W))
14 | val arcache = Output(UInt(4.W))
15 | val arprot = Output(UInt(3.W))
16 | val arvalid = Output(Bool())
17 | val arready = Input(Bool())
18 |
19 | // Read back
20 | val rid = Input(UInt(4.W))
21 | val rdata = Input(UInt(Param.Width.Axi.data))
22 | val rresp = Input(UInt(2.W))
23 | val rlast = Input(Bool())
24 | val rvalid = Input(Bool())
25 | val rready = Output(Bool())
26 |
27 | // Write request
28 | val awid = Output(UInt(4.W))
29 | val awaddr = Output(UInt(spec.Width.Axi.addr))
30 | val awlen = Output(UInt(8.W))
31 | val awsize = Output(UInt(3.W))
32 | val awburst = Output(UInt(2.W))
33 | val awlock = Output(UInt(2.W))
34 | val awcache = Output(UInt(4.W))
35 | val awprot = Output(UInt(3.W))
36 | val awvalid = Output(Bool())
37 | val awready = Input(Bool())
38 |
39 | // Write data
40 | val wid = Output(UInt(4.W))
41 | val wdata = Output(UInt(Param.Width.Axi.data))
42 | val wstrb = Output(UInt(Param.Width.Axi.strb))
43 | val wlast = Output(Bool())
44 | val wvalid = Output(Bool())
45 | val wready = Input(Bool())
46 |
47 | // Write back
48 | val bid = Input(UInt(4.W))
49 | val bresp = Input(UInt(2.W))
50 | val bvalid = Input(Bool())
51 | val bready = Output(Bool())
52 | }
53 |
--------------------------------------------------------------------------------
/src/src/common/bundles/BackendRedirectPcNdPort.scala:
--------------------------------------------------------------------------------
1 | package common.bundles
2 |
3 | import chisel3._
4 | import chisel3.experimental.BundleLiterals._
5 | import spec._
6 |
7 | class BackendRedirectPcNdPort extends Bundle {
8 | val en = Bool()
9 | val pcAddr = UInt(Width.Reg.data)
10 | val ftqId = UInt(Param.BPU.Width.id)
11 | }
12 |
13 | object BackendRedirectPcNdPort {
14 | def default = (new BackendRedirectPcNdPort).Lit(
15 | _.en -> false.B,
16 | _.pcAddr -> zeroWord,
17 | _.ftqId -> 0.U
18 | )
19 | }
20 |
--------------------------------------------------------------------------------
/src/src/common/bundles/BaseStagePort.scala:
--------------------------------------------------------------------------------
1 | package common.bundles
2 |
3 | import chisel3._
4 | import chisel3.util._
5 |
6 | class BaseStagePort[InT <: Data, OutT <: Data, PT <: Data](
7 | inNdFactory: InT,
8 | outNdFactory: OutT,
9 | peerFactory: => Option[PT])
10 | extends Bundle {
11 | val in = Flipped(Decoupled(inNdFactory))
12 | val out = Decoupled(outNdFactory)
13 | val peer = peerFactory
14 | val isFlush = Input(Bool())
15 | }
16 |
--------------------------------------------------------------------------------
/src/src/common/bundles/MultiBaseStagePort.scala:
--------------------------------------------------------------------------------
1 | package common.bundles
2 |
3 | import chisel3._
4 | import chisel3.util._
5 |
6 | class MultiBaseStagePort[InT <: Data, OutT <: Data, PT <: Data](
7 | inNdFactory: InT,
8 | outNdFactory: OutT,
9 | peerFactory: => Option[PT],
10 | inNum: Int,
11 | outNum: Int)
12 | extends Bundle {
13 | val ins = Vec(inNum, Flipped(Decoupled(inNdFactory)))
14 | val outs = Vec(outNum, Decoupled(outNdFactory))
15 | val peer = peerFactory
16 | val isFlush = Input(Bool())
17 | }
18 |
--------------------------------------------------------------------------------
/src/src/common/bundles/PassThroughPort.scala:
--------------------------------------------------------------------------------
1 | package common.bundles
2 |
3 | import chisel3._
4 |
5 | class PassThroughPort[PortT <: Data](signalFactory: PortT) extends Bundle {
6 | val in = Input(signalFactory)
7 | val out = Output(signalFactory)
8 | }
9 |
--------------------------------------------------------------------------------
/src/src/common/bundles/RfAccessInfoNdPort.scala:
--------------------------------------------------------------------------------
1 | package common.bundles
2 |
3 | import chisel3._
4 | import chisel3.experimental.BundleLiterals._
5 | import spec._
6 |
7 | class RfAccessInfoNdPort(addrWidth: internal.firrtl.Width = Width.Reg.addr) extends Bundle {
8 | val en = Bool()
9 | val addr = UInt(addrWidth)
10 | }
11 |
12 | object RfAccessInfoNdPort {
13 | def default = (new RfAccessInfoNdPort).Lit(
14 | _.en -> false.B,
15 | _.addr -> 0.U
16 | )
17 | }
18 |
--------------------------------------------------------------------------------
/src/src/common/bundles/RfReadPort.scala:
--------------------------------------------------------------------------------
1 | package common.bundles
2 |
3 | import chisel3._
4 | import spec._
5 |
6 | class RfReadPort extends Bundle {
7 | val en = Input(Bool())
8 | val addr = Input(UInt(Width.Reg.addr))
9 | val data = Output(UInt(Width.Reg.data))
10 | }
11 |
--------------------------------------------------------------------------------
/src/src/common/bundles/RfWriteNdPort.scala:
--------------------------------------------------------------------------------
1 | package common.bundles
2 |
3 | import chisel3._
4 | import chisel3.experimental.BundleLiterals._
5 | import spec._
6 |
7 | class RfWriteNdPort extends Bundle {
8 | val en = Bool()
9 | val addr = UInt(Width.Reg.addr)
10 | val data = UInt(Width.Reg.data)
11 | }
12 |
13 | object RfWriteNdPort {
14 | def default = (new RfWriteNdPort).Lit(
15 | _.en -> false.B,
16 | _.addr -> 0.U,
17 | _.data -> 0.U
18 | )
19 | }
20 |
--------------------------------------------------------------------------------
/src/src/common/enums/ReadWriteSel.scala:
--------------------------------------------------------------------------------
1 | package common.enums
2 |
3 | import chisel3.ChiselEnum
4 |
5 | object ReadWriteSel extends ChiselEnum {
6 | val read, write = Value
7 | }
8 |
--------------------------------------------------------------------------------
/src/src/control/CsrScoreboard.scala:
--------------------------------------------------------------------------------
1 | package control
2 |
3 | import chisel3._
4 | import chisel3.util.Valid
5 | import control.bundles.CsrWriteNdPort
6 |
7 | class CsrScoreboard extends Module {
8 | val io = IO(new Bundle {
9 | val csrWriteStorePort = Input(Valid(new CsrWriteNdPort))
10 | val csrWritePort = Output(new CsrWriteNdPort)
11 |
12 | val isFlush = Input(Bool())
13 | })
14 |
15 | val isWriteValid = RegInit(true.B)
16 |
17 | val csrWriteReg = RegInit(CsrWriteNdPort.default)
18 | io.csrWritePort := csrWriteReg
19 |
20 | when(io.isFlush) {
21 | isWriteValid := true.B
22 | csrWriteReg.en := false.B
23 | }.elsewhen(io.csrWriteStorePort.valid && isWriteValid) {
24 | isWriteValid := false.B
25 | csrWriteReg := io.csrWriteStorePort.bits
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/src/src/control/StableCounter.scala:
--------------------------------------------------------------------------------
1 | package control
2 |
3 | import chisel3._
4 | import control.bundles.StableCounterReadPort
5 | import spec._
6 |
7 | class StableCounter extends Module {
8 |
9 | val io = IO(new StableCounterReadPort)
10 |
11 | val timer64 = RegInit(0.U(doubleWordLength.W))
12 | timer64 := timer64 + 1.U
13 |
14 | io.output := timer64
15 |
16 | // io.output := zeroWord
17 | // io.isMatch := false.B
18 | // switch(io.exeOp) {
19 |
20 | // is(ExeInst.Op.rdcntvl_w) {
21 | // io.isMatch := true.B
22 | // io.output := timer64(wordLength - 1, 0)
23 | // }
24 |
25 | // is(ExeInst.Op.rdcntvh_w) {
26 | // io.isMatch := true.B
27 | // io.output := timer64(doubleWordLength - 1, wordLength)
28 | // }
29 | // }
30 |
31 | // if (isDiffTest) {
32 | // io.difftest match {
33 | // case Some(d) =>
34 | // d.isCnt := RegNext(io.isMatch, false.B)
35 | // d.value := RegNext(timer64, 0.U)
36 | // case None =>
37 | // }
38 | // }
39 | }
40 |
--------------------------------------------------------------------------------
/src/src/control/bundles/BadVAddrSetBundle.scala:
--------------------------------------------------------------------------------
1 | package control.bundles
2 |
3 | import chisel3._
4 | import spec._
5 |
6 | class BadVAddrSetBundle extends Bundle {
7 | val en = Bool()
8 | val addr = UInt(Width.Reg.data)
9 | }
10 |
11 | object BadVAddrSetBundle {
12 | def default = 0.U.asTypeOf(new BadVAddrSetBundle)
13 | }
14 |
--------------------------------------------------------------------------------
/src/src/control/bundles/BranchFlushInfo.scala:
--------------------------------------------------------------------------------
1 | package control.bundles
2 |
3 | import chisel3._
4 | import spec._
5 |
6 | class BranchFlushInfo extends Bundle {
7 | val en = Bool()
8 | val robId = UInt(Param.Width.Rob.id)
9 | }
10 |
11 | object BranchFlushInfo {
12 | def default = 0.U.asTypeOf(new BranchFlushInfo)
13 | }
14 |
--------------------------------------------------------------------------------
/src/src/control/bundles/CsrReadPort.scala:
--------------------------------------------------------------------------------
1 | package control.bundles
2 |
3 | import chisel3._
4 | import spec._
5 |
6 | class CsrReadPort extends Bundle {
7 | val en = Input(Bool())
8 | val addr = Input(UInt(Width.Csr.addr))
9 | val data = Output(UInt(Width.Csr.data))
10 | }
11 |
--------------------------------------------------------------------------------
/src/src/control/bundles/CsrValuePort.scala:
--------------------------------------------------------------------------------
1 | package control.bundles
2 |
3 | import chisel3._
4 | import control.csrBundles._
5 |
6 | class CsrValuePort extends Bundle {
7 | val crmd = new CrmdBundle
8 | val prmd = new PrmdBundle
9 | val euen = new EuenBundle
10 | val ecfg = new EcfgBundle
11 | val estat = new EstatBundle
12 | val era = new EraBundle
13 | val badv = new BadvBundle
14 | val eentry = new EentryBundle
15 | val tlbidx = new TlbidxBundle
16 | val tlbehi = new TlbehiBundle
17 | val tlbelo0 = new TlbeloBundle
18 | val tlbelo1 = new TlbeloBundle
19 | val asid = new AsidBundle
20 | val pgdl = new PgdlBundle
21 | val pgdh = new PgdhBundle
22 | val pgd = new PgdBundle
23 | val cpuid = new CpuidBundle
24 | val save0 = new CsrSaveBundle
25 | val save1 = new CsrSaveBundle
26 | val save2 = new CsrSaveBundle
27 | val save3 = new CsrSaveBundle
28 | val tid = new TidBundle
29 | val tcfg = new TcfgBundle
30 | val tval = new TvalBundle
31 | val ticlr = new TiclrBundle
32 | val llbctl = new LlbctlBundle
33 | val tlbrentry = new TlbrentryBundle
34 | val dmw0 = new DmwBundle
35 | val dmw1 = new DmwBundle
36 | }
37 |
38 | object CsrValuePort {
39 | def default = 0.U.asTypeOf(new CsrValuePort)
40 | }
41 |
--------------------------------------------------------------------------------
/src/src/control/bundles/CsrWriteNdPort.scala:
--------------------------------------------------------------------------------
1 | package control.bundles
2 |
3 | import chisel3._
4 | import chisel3.experimental.BundleLiterals._
5 | import spec._
6 |
7 | class CsrWriteNdPort extends Bundle {
8 | val en = Bool()
9 | val addr = UInt(Width.Csr.addr)
10 | val data = UInt(Width.Csr.data)
11 | }
12 |
13 | object CsrWriteNdPort {
14 | def default = (new CsrWriteNdPort).Lit(
15 | _.en -> false.B,
16 | _.addr -> zeroWord,
17 | _.data -> zeroWord
18 | )
19 | }
20 |
--------------------------------------------------------------------------------
/src/src/control/bundles/CuToCsrNdPort.scala:
--------------------------------------------------------------------------------
1 | package control.bundles
2 |
3 | import chisel3._
4 | import spec._
5 |
6 | class CuToCsrNdPort extends Bundle {
7 | val exceptionFlush = Bool()
8 | val ertnFlush = Bool()
9 | val era = UInt(Width.Reg.data)
10 | val ecodeBundle = new EcodeBundle
11 | // tlb重填失效
12 | val tlbRefillException = Bool()
13 | // 出错虚地址
14 | val badVAddrSet = new BadVAddrSetBundle
15 | // llbit设置
16 | val llbitSet = new LLBitSetBundle
17 | }
18 |
19 | object CuToCsrNdPort {
20 | def default = 0.U.asTypeOf(new CuToCsrNdPort)
21 | }
22 |
--------------------------------------------------------------------------------
/src/src/control/bundles/DifftestTimerNdPort.scala:
--------------------------------------------------------------------------------
1 | package control.bundles
2 |
3 | import chisel3._
4 | import spec.doubleWordLength
5 |
6 | class DifftestTimerNdPort extends Bundle {
7 | val isCnt = Bool()
8 | val timer64 = UInt(doubleWordLength.W)
9 | }
10 |
11 | object DifftestTimerNdPort {
12 | def default = 0.U.asTypeOf(new DifftestTimerNdPort)
13 | }
14 |
--------------------------------------------------------------------------------
/src/src/control/bundles/EcodeBundle.scala:
--------------------------------------------------------------------------------
1 | package control.bundles
2 |
3 | import chisel3._
4 | import spec._
5 |
6 | class EcodeBundle extends Bundle {
7 | val esubcode = UInt(Csr.Estat.Width.esubcode)
8 | val ecode = UInt(Csr.Estat.Width.ecode)
9 | }
10 |
--------------------------------------------------------------------------------
/src/src/control/bundles/LLBitSetBundle.scala:
--------------------------------------------------------------------------------
1 | package control.bundles
2 |
3 | import chisel3._
4 |
5 | class LLBitSetBundle extends Bundle {
6 | val en = Bool()
7 | val setValue = Bool()
8 | }
9 |
10 | object LLBitSetBundle {
11 | def default = 0.U.asTypeOf(new LLBitSetBundle)
12 | }
13 |
--------------------------------------------------------------------------------
/src/src/control/bundles/PipelineControlNdPort.scala:
--------------------------------------------------------------------------------
1 | package control.bundles
2 |
3 | import chisel3._
4 | import chisel3.experimental.BundleLiterals._
5 |
6 | class PipelineControlNdPort extends Bundle {
7 | val flush = Bool()
8 | val clear = Bool()
9 | val stall = Bool()
10 | }
11 |
12 | object PipelineControlNdPort {
13 | def default = (new PipelineControlNdPort).Lit(
14 | _.flush -> false.B,
15 | _.clear -> false.B,
16 | _.stall -> false.B
17 | )
18 | }
19 |
--------------------------------------------------------------------------------
/src/src/control/bundles/StableCounterReadPort.scala:
--------------------------------------------------------------------------------
1 | package control.bundles
2 |
3 | import chisel3._
4 | import spec._
5 |
6 | class StableCounterReadPort extends Bundle {
7 | val output = Output(UInt(doubleWordLength.W))
8 | // val difftest = if (isDiffTest) {
9 | // Some(Output(new Bundle() {
10 | // val isCnt = Output(Bool())
11 | // val value = Output(UInt(doubleWordLength.W))
12 | // }))
13 | // } else None
14 | }
15 |
--------------------------------------------------------------------------------
/src/src/control/csrRegsBundles/AsidBundle.scala:
--------------------------------------------------------------------------------
1 | package control.csrBundles
2 |
3 | import chisel3._
4 |
5 | class AsidBundle extends Bundle {
6 | val zero1 = UInt(8.W)
7 | val asidbits = UInt(8.W)
8 | val zero2 = UInt(6.W)
9 | val asid = UInt(10.W)
10 | }
11 |
12 | object AsidBundle {
13 | def default = 0.U.asTypeOf(new AsidBundle)
14 | }
15 |
--------------------------------------------------------------------------------
/src/src/control/csrRegsBundles/BadvBundle.scala:
--------------------------------------------------------------------------------
1 | package control.csrBundles
2 |
3 | import chisel3._
4 | import spec._
5 |
6 | class BadvBundle extends Bundle {
7 | val vaddr = UInt(Width.Reg.data)
8 | }
9 |
10 | object BadvBundle {
11 | def default = 0.U.asTypeOf(new BadvBundle)
12 | }
13 |
--------------------------------------------------------------------------------
/src/src/control/csrRegsBundles/CpuidBundle.scala:
--------------------------------------------------------------------------------
1 | package control.csrBundles
2 |
3 | import chisel3._
4 |
5 | class CpuidBundle extends Bundle {
6 | val zero = UInt(23.W)
7 | val coreId = UInt(9.W)
8 | }
9 |
10 | object CpuidBundle {
11 | def default = 0.U.asTypeOf(new CpuidBundle)
12 | }
13 |
--------------------------------------------------------------------------------
/src/src/control/csrRegsBundles/CrmdBundle.scala:
--------------------------------------------------------------------------------
1 | package control.csrBundles
2 |
3 | import chisel3._
4 | import chisel3.experimental.BundleLiterals._
5 |
6 | class CrmdBundle extends Bundle {
7 | val zero = UInt(23.W)
8 | val datm = UInt(2.W)
9 | val datf = UInt(2.W)
10 | val pg = Bool() // 映射地址翻译模式使能,高有效
11 | // 直接地址翻译使能,高有效
12 | val da = Bool()
13 | val ie = Bool()
14 | val plv = UInt(2.W)
15 | }
16 |
17 | object CrmdBundle {
18 | def default = (new CrmdBundle).Lit(
19 | _.zero -> 0.U,
20 | _.datm -> 0.U,
21 | _.datf -> 0.U,
22 | _.pg -> false.B,
23 | _.da -> true.B, // Attention!: it is '1'
24 | _.ie -> false.B,
25 | _.plv -> 0.U
26 | )
27 | }
28 |
--------------------------------------------------------------------------------
/src/src/control/csrRegsBundles/CsrSaveBundle.scala:
--------------------------------------------------------------------------------
1 | package control.csrBundles
2 |
3 | import chisel3._
4 | import spec._
5 |
6 | class CsrSaveBundle extends Bundle {
7 | val data = UInt(Width.Reg.data)
8 | }
9 |
10 | object CsrSaveBundle {
11 | def default = 0.U.asTypeOf(new CsrSaveBundle)
12 | }
13 |
--------------------------------------------------------------------------------
/src/src/control/csrRegsBundles/DmwBundle.scala:
--------------------------------------------------------------------------------
1 | package control.csrBundles
2 |
3 | import chisel3._
4 |
5 | class DmwBundle extends Bundle {
6 | val vseg = UInt(3.W)
7 | val zero1 = Bool()
8 | val pseg = UInt(3.W)
9 | val zero2 = UInt(19.W)
10 | val mat = UInt(2.W)
11 | val plv3 = Bool()
12 | val zero3 = UInt(2.W)
13 | val plv0 = Bool()
14 | }
15 |
16 | object DmwBundle {
17 | def default = 0.U.asTypeOf(new DmwBundle)
18 | }
19 |
--------------------------------------------------------------------------------
/src/src/control/csrRegsBundles/EcfgBundle.scala:
--------------------------------------------------------------------------------
1 | package control.csrBundles
2 |
3 | import chisel3._
4 |
5 | class EcfgBundle extends Bundle {
6 | val zero1 = UInt(19.W)
7 | val lie2 = UInt(2.W)
8 | val zero2 = UInt(1.W)
9 | val lie1 = UInt(10.W)
10 | }
11 |
12 | object EcfgBundle {
13 | def default = 0.U.asTypeOf(new EcfgBundle)
14 | }
15 |
--------------------------------------------------------------------------------
/src/src/control/csrRegsBundles/EentryBundle.scala:
--------------------------------------------------------------------------------
1 | package control.csrBundles
2 |
3 | import chisel3._
4 |
5 | class EentryBundle extends Bundle {
6 | val va = UInt(26.W)
7 | val zero = UInt(6.W)
8 | }
9 |
10 | object EentryBundle {
11 | def default = 0.U.asTypeOf(new EentryBundle)
12 | }
13 |
--------------------------------------------------------------------------------
/src/src/control/csrRegsBundles/EraBundle.scala:
--------------------------------------------------------------------------------
1 | package control.csrBundles
2 |
3 | import chisel3._
4 | import spec._
5 |
6 | class EraBundle extends Bundle {
7 | val pc = UInt(Width.Reg.data)
8 | }
9 |
10 | object EraBundle {
11 | def default = 0.U.asTypeOf(new EraBundle)
12 | }
13 |
--------------------------------------------------------------------------------
/src/src/control/csrRegsBundles/EstatBundle.scala:
--------------------------------------------------------------------------------
1 | package control.csrBundles
2 |
3 | import chisel3._
4 | import spec._
5 |
6 | class EstatBundle extends Bundle {
7 | val zero1 = Bool()
8 | val esubcode = UInt(Csr.Estat.Width.esubcode)
9 | val ecode = UInt(Csr.Estat.Width.ecode)
10 | val zero2 = UInt(3.W)
11 | val is_ipInt = Bool()
12 | val is_timeInt = Bool()
13 | val zero3 = Bool()
14 | val is_hardwareInt = UInt(8.W)
15 | val is_softwareInt = UInt(2.W)
16 | }
17 |
18 | object EstatBundle {
19 | def default = 0.U.asTypeOf(new EstatBundle)
20 | }
21 |
--------------------------------------------------------------------------------
/src/src/control/csrRegsBundles/EuenBundle.scala:
--------------------------------------------------------------------------------
1 | package control.csrBundles
2 |
3 | import chisel3._
4 |
5 | class EuenBundle extends Bundle {
6 | val zero = UInt(31.W)
7 | val fpe = Bool()
8 | }
9 |
10 | object EuenBundle {
11 | def default = 0.U.asTypeOf(new EuenBundle)
12 | }
13 |
--------------------------------------------------------------------------------
/src/src/control/csrRegsBundles/LlbctlBundle.scala:
--------------------------------------------------------------------------------
1 | package control.csrBundles
2 |
3 | import chisel3._
4 |
5 | class LlbctlBundle extends Bundle {
6 | val zero = UInt(29.W)
7 | val klo = Bool()
8 | val wcllb = Bool()
9 | val rollb = Bool()
10 | }
11 |
12 | object LlbctlBundle {
13 | def default = 0.U.asTypeOf(new LlbctlBundle)
14 | }
15 |
--------------------------------------------------------------------------------
/src/src/control/csrRegsBundles/PgdBundle.scala:
--------------------------------------------------------------------------------
1 | package control.csrBundles
2 |
3 | import chisel3._
4 |
5 | class PgdBundle extends Bundle {
6 | val base = UInt(20.W)
7 | val zero = UInt(12.W)
8 | }
9 |
10 | object PgdBundle {
11 | def default = 0.U.asTypeOf(new PgdBundle)
12 | }
13 |
--------------------------------------------------------------------------------
/src/src/control/csrRegsBundles/PgdhBundle.scala:
--------------------------------------------------------------------------------
1 | package control.csrBundles
2 |
3 | import chisel3._
4 |
5 | class PgdhBundle extends Bundle {
6 | val base = UInt(20.W)
7 | val zero = UInt(12.W)
8 | }
9 |
10 | object PgdhBundle {
11 | def default = 0.U.asTypeOf(new PgdhBundle)
12 | }
13 |
--------------------------------------------------------------------------------
/src/src/control/csrRegsBundles/PgdlBundle.scala:
--------------------------------------------------------------------------------
1 | package control.csrBundles
2 |
3 | import chisel3._
4 |
5 | class PgdlBundle extends Bundle {
6 | val base = UInt(20.W)
7 | val zero = UInt(12.W)
8 | }
9 |
10 | object PgdlBundle {
11 | def default = 0.U.asTypeOf(new PgdlBundle)
12 | }
13 |
--------------------------------------------------------------------------------
/src/src/control/csrRegsBundles/PrmdBundle.scala:
--------------------------------------------------------------------------------
1 | package control.csrBundles
2 |
3 | import chisel3._
4 |
5 | class PrmdBundle extends Bundle {
6 | val zero = UInt(29.W)
7 | val pie = Bool()
8 | val pplv = UInt(2.W)
9 | }
10 |
11 | object PrmdBundle {
12 | def default = 0.U.asTypeOf(new PrmdBundle)
13 | }
14 |
--------------------------------------------------------------------------------
/src/src/control/csrRegsBundles/TcfgBundle.scala:
--------------------------------------------------------------------------------
1 | package control.csrBundles
2 |
3 | import chisel3._
4 | import spec._
5 |
6 | class TcfgBundle extends Bundle {
7 | val initVal = UInt((Csr.TimeVal.Width.timeVal - 2).W)
8 | val periodic = Bool()
9 | val en = Bool()
10 | }
11 |
12 | object TcfgBundle {
13 | def default = 0.U.asTypeOf(new TcfgBundle)
14 | }
15 |
--------------------------------------------------------------------------------
/src/src/control/csrRegsBundles/TiclrBundle.scala:
--------------------------------------------------------------------------------
1 | package control.csrBundles
2 |
3 | import chisel3._
4 |
5 | class TiclrBundle extends Bundle {
6 | val zero = UInt(31.W)
7 | val clr = Bool()
8 | }
9 |
10 | object TiclrBundle {
11 | def default = 0.U.asTypeOf(new TiclrBundle)
12 | }
13 |
--------------------------------------------------------------------------------
/src/src/control/csrRegsBundles/TidBundle.scala:
--------------------------------------------------------------------------------
1 | package control.csrBundles
2 |
3 | import chisel3._
4 | import spec._
5 |
6 | class TidBundle extends Bundle {
7 | val tid = UInt(Width.Reg.data)
8 | }
9 |
10 | object TidBundle {
11 | def default = 0.U.asTypeOf(new TidBundle)
12 | }
13 |
--------------------------------------------------------------------------------
/src/src/control/csrRegsBundles/TlbehiBundle.scala:
--------------------------------------------------------------------------------
1 | package control.csrBundles
2 |
3 | import chisel3._
4 |
5 | class TlbehiBundle extends Bundle {
6 | val vppn = UInt(19.W)
7 | val zero = UInt(13.W)
8 | }
9 |
10 | object TlbehiBundle {
11 | def default = 0.U.asTypeOf(new TlbehiBundle)
12 | }
13 |
--------------------------------------------------------------------------------
/src/src/control/csrRegsBundles/TlbeloBundle.scala:
--------------------------------------------------------------------------------
1 | package control.csrBundles
2 |
3 | import chisel3._
4 |
5 | class TlbeloBundle extends Bundle {
6 | val ppn = UInt((spec.Csr.Tlbelo.Width.palen - 12).W)
7 | val zero = Bool()
8 | val g = Bool()
9 | val mat = UInt(2.W)
10 | val plv = UInt(2.W)
11 | val d = Bool()
12 | val v = Bool()
13 | }
14 |
15 | object TlbeloBundle {
16 | def default = 0.U.asTypeOf(new TlbeloBundle)
17 | }
18 |
--------------------------------------------------------------------------------
/src/src/control/csrRegsBundles/TlbidxBundle.scala:
--------------------------------------------------------------------------------
1 | package control.csrBundles
2 |
3 | import chisel3._
4 | import spec._
5 |
6 | class TlbidxBundle extends Bundle {
7 | val ne = Bool()
8 | val zero1 = Bool()
9 | val ps = UInt(6.W)
10 | val zero2 = UInt((24 - Csr.Tlbidx.Width.index).W)
11 | val index = UInt(Csr.Tlbidx.Width.index.W)
12 | }
13 |
14 | object TlbidxBundle {
15 | def default = 0.U.asTypeOf(new TlbidxBundle)
16 | }
17 |
--------------------------------------------------------------------------------
/src/src/control/csrRegsBundles/TlbrentryBundle.scala:
--------------------------------------------------------------------------------
1 | package control.csrBundles
2 |
3 | import chisel3._
4 |
5 | class TlbrentryBundle extends Bundle {
6 | val pa = UInt(26.W)
7 | val zero = UInt(6.W)
8 | }
9 |
10 | object TlbrentryBundle {
11 | def default = 0.U.asTypeOf(new TlbrentryBundle)
12 | }
13 |
--------------------------------------------------------------------------------
/src/src/control/csrRegsBundles/TvalBundle.scala:
--------------------------------------------------------------------------------
1 | package control.csrBundles
2 |
3 | import chisel3._
4 | import spec._
5 |
6 | class TvalBundle extends Bundle {
7 | val timeVal = UInt(Csr.TimeVal.Width.timeVal.W)
8 | }
9 |
10 | object TvalBundle {
11 | def default = 0.U.asTypeOf(new TvalBundle)
12 | }
13 |
--------------------------------------------------------------------------------
/src/src/control/enums/ExceptionPos.scala:
--------------------------------------------------------------------------------
1 | package control.enums
2 |
3 | import chisel3._
4 |
5 | object ExceptionPos extends ChiselEnum {
6 | val none, frontend, backend = Value
7 | }
8 |
--------------------------------------------------------------------------------
/src/src/execution/Clz.scala:
--------------------------------------------------------------------------------
1 | package execution
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import spec._
6 |
7 | /** 并行计算前导0数量(2022)
8 | */
9 | class Clz extends Module {
10 |
11 | val io = IO(new Bundle {
12 | val input = Input(UInt(wordLength.W))
13 | val output = Output(UInt(wordLog.W))
14 | })
15 |
16 | // 每4位判断是否全0
17 | val subClz = WireDefault(
18 | VecInit(
19 | Seq
20 | .range(0, 8)
21 | .map(i => {
22 | ~io.input(i * 4 + 3, i * 4).orR
23 | })
24 | ).asUInt
25 | )
26 |
27 | // 每4位中,前3位的前导0数量
28 | val subsubClzTable = VecInit(
29 | "b11".U(2.W), // 000
30 | "b10".U(2.W), // 001
31 | "b01".U(2.W), // 010
32 | "b01".U(2.W), // 011
33 | "b00".U(2.W), // 100
34 | "b00".U(2.W), // 101
35 | "b00".U(2.W), // 110
36 | "b00".U(2.W) // 111
37 | )
38 |
39 | // 分成的8块的前3位前导0的数量
40 | val subsubClz = WireDefault(
41 | VecInit(
42 | Seq
43 | .range(0, 8)
44 | .map(i => {
45 | subsubClzTable(io.input(i * 4 + 3, i * 4 + 1))
46 | })
47 | )
48 | )
49 |
50 | val clzResult4 = Wire(Bool())
51 | val clzResult3 = Wire(Bool())
52 | val clzResult2 = Wire(Bool())
53 |
54 | clzResult4 := subClz(7, 4).andR // upper 16 all zero
55 | clzResult3 := Mux(
56 | clzResult4,
57 | subClz(3, 2).andR, // upper 24 all zero
58 | subClz(7, 6).andR // upper 8 all zero
59 | )
60 |
61 | clzResult2 := (subClz(7) && !subClz(6)) || // upper 4 all zero
62 | (subClz(7, 5).andR && !subClz(4)) || // upper 12
63 | (subClz(7, 3).andR && !subClz(2)) || // upper 20
64 | (subClz(7, 1).andR && !subClz(0)) // upper 28
65 |
66 | /** 切分成4块,分别求解clzResult末两位值 如末8位,i = 0,若subClz(1)===1,7-4位全0,看3-0位 否则7-4位有1,看7-4位
67 | */
68 |
69 | val clzResult10Selector = VecInit(
70 | Seq.range(3, -1, -1).map(i => subsubClz(Cat(i.U(2.W), ~subClz(i * 2 + 1))))
71 | )
72 |
73 | val clzResult10 = clzResult10Selector(Cat(clzResult4, clzResult3))
74 |
75 | io.output := Cat(clzResult4, clzResult3, clzResult2, clzResult10)
76 | }
77 |
--------------------------------------------------------------------------------
/src/src/execution/Mul.scala:
--------------------------------------------------------------------------------
1 | package execution
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import execution.bundles.MulDivInstNdPort
6 | import spec.doubleWordLength
7 |
8 | object MulState extends ChiselEnum {
9 | val free, calc, finish = Value
10 | }
11 |
12 | class Mul extends Module {
13 | val io = IO(new Bundle {
14 | val mulInst = Input(Valid(new MulDivInstNdPort))
15 | val mulResult = Output(Valid(UInt(doubleWordLength.W)))
16 | val isFlush = Input(Bool())
17 | })
18 |
19 | val stateReg = RegInit(MulState.free)
20 |
21 | val lopReg = RegNext(io.mulInst.bits.leftOperand, 0.U)
22 | val ropReg = RegNext(io.mulInst.bits.rightOperand, 0.U)
23 | val isSignedReg = RegNext(io.mulInst.bits.isSigned, false.B)
24 |
25 | val signedResult = RegNext(lopReg.asSInt * ropReg.asSInt, 0.S)
26 | val unsignedResult = RegNext(lopReg * ropReg, 0.U)
27 |
28 | io.mulResult.valid := false.B
29 | io.mulResult.bits := DontCare
30 |
31 | switch(stateReg) {
32 | is(MulState.free) {
33 | when(io.mulInst.valid) {
34 | stateReg := MulState.calc
35 | }
36 | }
37 |
38 | is(MulState.calc) {
39 | stateReg := MulState.finish
40 | }
41 | is(MulState.finish) {
42 | stateReg := MulState.free
43 | io.mulResult.valid := true.B
44 | io.mulResult.bits := Mux(
45 | isSignedReg,
46 | signedResult.asUInt,
47 | unsignedResult
48 | )
49 | }
50 | }
51 |
52 | when(io.isFlush) {
53 | stateReg := MulState.free
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/src/execution/bundles/AluInstNdPort.scala:
--------------------------------------------------------------------------------
1 | package execution.bundles
2 |
3 | import chisel3._
4 | import spec._
5 |
6 | class AluInstNdPort extends Bundle {
7 | val op = UInt(Param.Width.exeOp)
8 | val leftOperand = UInt(Width.Reg.data)
9 | val rightOperand = UInt(Width.Reg.data)
10 | val jumpBranchAddr = UInt(Width.Reg.data)
11 | }
12 |
--------------------------------------------------------------------------------
/src/src/execution/bundles/AluResultNdPort.scala:
--------------------------------------------------------------------------------
1 | package execution.bundles
2 |
3 | import chisel3._
4 | import chisel3.experimental.BundleLiterals._
5 | import pipeline.complex.execution.bundles.JumpBranchInfoNdPort
6 | import spec._
7 |
8 | class AluResultNdPort extends Bundle {
9 | val logic = UInt(Width.Reg.data)
10 | val shift = UInt(Width.Reg.data)
11 | val arithmetic = UInt(Width.Reg.data)
12 | val jumpBranchInfo = new JumpBranchInfoNdPort
13 | }
14 |
15 | object AluResultNdPort {
16 | def default = (new AluResultNdPort).Lit(
17 | _.logic -> zeroWord,
18 | _.shift -> zeroWord,
19 | _.arithmetic -> zeroWord,
20 | _.jumpBranchInfo -> JumpBranchInfoNdPort.default
21 | )
22 | }
23 |
--------------------------------------------------------------------------------
/src/src/execution/bundles/MulDivInstNdPort.scala:
--------------------------------------------------------------------------------
1 | package execution.bundles
2 |
3 | import chisel3._
4 | import spec._
5 |
6 | class MulDivInstNdPort extends Bundle {
7 | val isSigned = Bool()
8 | val leftOperand = UInt(Width.Reg.data)
9 | val rightOperand = UInt(Width.Reg.data)
10 | }
11 |
--------------------------------------------------------------------------------
/src/src/frontend/InstFetch.scala:
--------------------------------------------------------------------------------
1 | package frontend
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import frontend.bundles.{FtqIFNdPort, ICacheAccessPort}
6 | import frontend.fetch._
7 | import memory.bundles.TlbTransPort
8 | import pipeline.common.bundles.{InstQueueEnqNdPort, MemCsrNdPort}
9 |
10 | class InstFetch extends Module {
11 | val io = IO(new Bundle {
12 | // <-> Frontend <-> FetchTargetQueue
13 | val ftqIFPort = Flipped(Decoupled(new FtqIFNdPort))
14 |
15 | // <-> Frontend <->ICache
16 | val accessPort = Flipped(new ICacheAccessPort)
17 |
18 | // <-> Frontend <-> Instrution queue
19 | val isFlush = Input(Bool())
20 | val instDequeuePort = Decoupled(new InstQueueEnqNdPort)
21 |
22 | // <-> Frontend <-> Tlb
23 | val tlbTrans = Flipped(new TlbTransPort)
24 | // <-> Frontend <-> csr
25 | val csr = Input(new MemCsrNdPort)
26 |
27 | // <-> Frontend <-> Pc,Ftq,
28 | val preDecodeRedirectPort = new InstPreDecodePeerPort
29 | })
30 |
31 | // InstAddr translate and mem stages
32 | val addrTransStage = Module(new InstAddrTransStage)
33 | val instReqStage = Module(new InstReqStage)
34 | val instResStage = Module(new InstResStage)
35 | val instPreDecodeStage = Module(new InstPreDecodeStage)
36 |
37 | // addrTransStage
38 | addrTransStage.io.isFlush := io.isFlush || instPreDecodeStage.io.peer.get.predecodeRedirect
39 | addrTransStage.io.in <> io.ftqIFPort
40 | addrTransStage.io.peer.foreach { p =>
41 | p.csr <> io.csr
42 | p.tlbTrans <> io.tlbTrans
43 | }
44 |
45 | // instReqStage
46 | instReqStage.io.isFlush := io.isFlush || instPreDecodeStage.io.peer.get.predecodeRedirect
47 | instReqStage.io.in <> addrTransStage.io.out
48 | instReqStage.io.peer.foreach { p =>
49 | p.memReq <> io.accessPort.req
50 | }
51 |
52 | // instResStage
53 | instResStage.io.isFlush := io.isFlush || instPreDecodeStage.io.peer.get.predecodeRedirect
54 | instResStage.io.in <> instReqStage.io.out
55 | instResStage.io.peer.foreach { p =>
56 | p.memRes <> io.accessPort.res
57 | }
58 |
59 | // instPreDecodeStage
60 | instPreDecodeStage.io.isFlush := io.isFlush
61 | instPreDecodeStage.io.in <> instResStage.io.out
62 | io.instDequeuePort <> instPreDecodeStage.io.out
63 | instPreDecodeStage.io.peer.foreach { p =>
64 | p <> io.preDecodeRedirectPort
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/src/frontend/InstFetchStage.scala:
--------------------------------------------------------------------------------
1 | package frontend
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import frontend.bundles.ICacheAccessPort
6 | import pipeline.common.bundles.FetchInstInfoBundle
7 | import spec._
8 |
9 | class InstFetchStage extends Module {
10 | val io = IO(new Bundle {
11 | val pc = Input(UInt(Width.Reg.data))
12 | val isPcNext = Output(Bool())
13 |
14 | // <-> Frontend <->ICache
15 | val accessPort = Flipped(new ICacheAccessPort)
16 |
17 | // <-> Frontend <-> Instrution queue
18 | val isFlush = Input(Bool())
19 | val instEnqueuePort = Decoupled(new FetchInstInfoBundle)
20 | })
21 |
22 | // io.instEnqueuePort.bits := FetchInstInfoBundle.default
23 | //
24 | // io.instEnqueuePort.bits.pcAddr := io.pc
25 | // io.instEnqueuePort.bits.inst := io.accessPort.res.read.data
26 | //
27 | // val stateReg = RegInit(State.idle)
28 | // stateReg := stateReg
29 | //
30 | // val shouldDiscardReg = RegInit(false.B) // Fallback: Follow
31 | // val shouldDiscard = WireInit(io.isFlush || shouldDiscardReg)
32 | //
33 | // val isCompleteReg = RegInit(false.B)
34 | // isCompleteReg := isCompleteReg
35 | // val lastInstReg = RegInit(0.U(Width.inst))
36 | // lastInstReg := lastInstReg
37 | //
38 | // // Fallbacks
39 | // io.isPcNext := false.B
40 | // io.accessPort.req.client.isValid := false.B
41 | // io.accessPort.req.client.addr := io.pc
42 | // io.instEnqueuePort.valid := false.B
43 | //
44 | // switch(stateReg) {
45 | // is(State.idle) { // State Value: 0
46 | // stateReg := State.request
47 | // }
48 | // is(State.request) { // State Value: 1
49 | // when(io.accessPort.req.isReady) {
50 | // stateReg := State.waitQueue
51 | // io.accessPort.req.client.isValid := true.B
52 | // isCompleteReg := false.B
53 | // }
54 | // }
55 | //
56 | // is(State.waitQueue) { // State Value: 2
57 | // shouldDiscardReg := shouldDiscard
58 | // when(io.accessPort.res.isComplete) {
59 | // isCompleteReg := true.B
60 | // lastInstReg := io.accessPort.res.read.data
61 | // }
62 | // when(isCompleteReg) {
63 | // io.instEnqueuePort.bits.inst := lastInstReg
64 | // }
65 | // when(io.accessPort.res.isComplete || isCompleteReg) {
66 | // io.instEnqueuePort.valid := true.B
67 | // when(shouldDiscard) {
68 | // io.instEnqueuePort.valid := false.B
69 | // stateReg := State.request
70 | // shouldDiscardReg := false.B
71 | // }.elsewhen(io.instEnqueuePort.ready) {
72 | // stateReg := State.request
73 | // shouldDiscardReg := false.B
74 | // io.isPcNext := true.B
75 | //
76 | // when(io.accessPort.req.isReady) {
77 | // stateReg := State.waitQueue
78 | // io.accessPort.req.client.addr := Mux(shouldDiscard, io.pc, io.pc + 4.U)
79 | // io.accessPort.req.client.isValid := true.B
80 | // isCompleteReg := false.B
81 | // }.otherwise {
82 | // stateReg := State.request
83 | // }
84 | // }
85 | // }
86 | // }
87 | // }
88 | }
89 |
--------------------------------------------------------------------------------
/src/src/frontend/NaiiveFetchStage.scala:
--------------------------------------------------------------------------------
1 | package frontend
2 |
3 | import axi.AxiMaster
4 | import axi.bundles.AxiMasterInterface
5 | import chisel3._
6 | import chisel3.util._
7 | import pipeline.common.bundles.FetchInstInfoBundle
8 | import spec.Param.{NaiiveFetchStageState => State}
9 | import spec._
10 |
11 | class NaiiveFetchStage extends Module {
12 | val io = IO(new Bundle {
13 | val pc = Input(UInt(Width.Reg.data))
14 | val isPcNext = Output(Bool())
15 | val axiMasterInterface = new AxiMasterInterface
16 | val instEnqueuePort = Decoupled(new FetchInstInfoBundle)
17 | val isFlush = Input(Bool())
18 | })
19 |
20 | val axiMaster = Module(new AxiMaster)
21 | axiMaster.io.axi <> io.axiMasterInterface
22 | axiMaster.io.we := false.B
23 | axiMaster.io.uncached := true.B
24 | axiMaster.io.size := 4.U // 32 bits
25 | axiMaster.io.dataIn := 0.U
26 | axiMaster.io.wstrb := 0.U
27 |
28 | val pcReg = RegInit(zeroWord)
29 | val instReg = RegInit(zeroWord)
30 | val pc = WireInit(pcReg)
31 | val inst = WireInit(instReg)
32 | io.instEnqueuePort.bits.pcAddr := pc
33 | io.instEnqueuePort.bits.inst := inst
34 |
35 | val nextState = WireInit(State.idle)
36 | val stateReg = RegNext(nextState, State.idle)
37 |
38 | val shouldDiscardReg = RegInit(false.B)
39 | val shouldDiscard = WireInit(io.isFlush || shouldDiscardReg)
40 | val isInstValidReg = RegInit(false.B)
41 | val isInstValid = WireInit(axiMaster.io.validOut || isInstValidReg)
42 |
43 | // Fallbacks
44 | io.isPcNext := false.B
45 | axiMaster.io.newRequest := false.B
46 | axiMaster.io.addr := pcReg
47 | io.instEnqueuePort.valid := false.B
48 | pc := pcReg
49 | inst := instReg
50 | pcReg := pcReg
51 | instReg := instReg
52 | shouldDiscardReg := false.B
53 | isInstValidReg := false.B
54 |
55 | switch(stateReg) {
56 | is(State.idle) { // State Value: 0
57 | nextState := State.request
58 | }
59 | is(State.request) { // State Value: 1
60 | when(io.isFlush || !axiMaster.io.readyOut) {
61 | nextState := State.waitQueue
62 | }.otherwise {
63 | nextState := State.waitQueue
64 |
65 | io.isPcNext := true.B
66 | axiMaster.io.newRequest := true.B
67 | axiMaster.io.addr := io.pc
68 | pc := io.pc
69 | pcReg := io.pc
70 | shouldDiscardReg := false.B
71 | }
72 | }
73 | is(State.waitQueue) { // State Value: 2
74 | shouldDiscardReg := shouldDiscard
75 | isInstValidReg := isInstValid
76 | when(axiMaster.io.validOut) {
77 | inst := axiMaster.io.dataOut
78 | instReg := axiMaster.io.dataOut
79 | }
80 | when(!isInstValid || !io.instEnqueuePort.ready) {
81 | nextState := State.waitQueue
82 | }.otherwise {
83 | nextState := State.request // non-stopping fetching instructions
84 | when(!shouldDiscard) {
85 | io.instEnqueuePort.valid := true.B
86 | }
87 | }
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/src/frontend/PreDecoder.scala:
--------------------------------------------------------------------------------
1 | package frontend
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import frontend.bundles.PreDecoderResultNdPort
6 | import spec.Inst.{_2RI16 => Inst}
7 | import spec.Width
8 |
9 | class PreDecoder extends Module {
10 | val io = IO(new Bundle {
11 | val pc = Input(UInt(Width.Reg.data))
12 | val inst = Input(UInt(Width.Reg.data))
13 | val result = Output(new PreDecoderResultNdPort)
14 | })
15 |
16 | // fall back
17 | io.result := PreDecoderResultNdPort.default
18 |
19 | val opcode = io.inst(31, 26)
20 | val rj = WireDefault(io.inst(9, 5))
21 | val rd = WireDefault(io.inst(4, 0))
22 | val imm26Sext = Cat(io.inst(9, 0), io.inst(25, 10)).asSInt
23 | val imm26SextShift2 = Wire(SInt(spec.Width.Reg.data))
24 | imm26SextShift2 := imm26Sext << 2
25 |
26 | // Inst Predecoder stage need muiti predecoder result
27 | // select the first inst which isJump(call,ret,direct uncond)
28 | // isBranch signal is use to check the error predict taken but actually not branch Inst
29 | switch(opcode) {
30 | is(Inst.b_) {
31 | io.result.isBranch := true.B
32 | io.result.isJump := true.B
33 | io.result.isImmJump := true.B
34 | io.result.jumpTargetAddr := imm26SextShift2.asUInt + io.pc
35 | }
36 | is(Inst.bl) {
37 | io.result.isBranch := true.B
38 | io.result.isJump := true.B
39 | io.result.isImmJump := true.B
40 | io.result.jumpTargetAddr := imm26SextShift2.asUInt + io.pc
41 | io.result.isCall := true.B
42 | }
43 | is(Inst.jirl) {
44 | io.result.isBranch := true.B
45 | io.result.isJump := true.B
46 | io.result.isImmJump := false.B
47 | io.result.isRet := rd === 0.U && rj === 1.U
48 | io.result.isCall := rd === 1.U
49 | }
50 | //
51 | is(Inst.beq, Inst.bne, Inst.blt, Inst.bge, Inst.bltu, Inst.bgeu) {
52 | io.result.isBranch := true.B
53 | }
54 |
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/src/frontend/SimpleFetchStage.scala:
--------------------------------------------------------------------------------
1 | package frontend
2 |
3 | import axi.AxiMaster
4 | import axi.bundles.AxiMasterInterface
5 | import chisel3._
6 | import chisel3.util._
7 | import pipeline.common.bundles.FetchInstInfoBundle
8 | import spec.Param.{SimpleFetchStageState => State}
9 | import spec._
10 |
11 | class SimpleFetchStage extends Module {
12 | val io = IO(new Bundle {
13 | val pc = Input(UInt(Width.Reg.data))
14 | val isPcNext = Output(Bool())
15 | val axiMasterInterface = new AxiMasterInterface
16 | val instEnqueuePort = Decoupled(new FetchInstInfoBundle)
17 | val isFlush = Input(Bool())
18 | })
19 |
20 | val axiMaster = Module(new AxiMaster)
21 | io.axiMasterInterface <> axiMaster.io.axi
22 | axiMaster.io.we := false.B
23 | axiMaster.io.uncached := true.B
24 | axiMaster.io.size := 4.U
25 | axiMaster.io.dataIn := 0.U
26 | axiMaster.io.wstrb := 0.U
27 |
28 | val axiReady = WireInit(axiMaster.io.readyOut)
29 | val axiReadValid = WireInit(axiMaster.io.validOut)
30 | val axiData = WireInit(axiMaster.io.dataOut)
31 |
32 | val nextState = WireInit(State.idle)
33 | val stateReg = RegNext(nextState, State.idle)
34 |
35 | val isPcNextReg = RegInit(false.B)
36 | io.isPcNext := isPcNextReg
37 | val axiReadRequestReg = RegInit(false.B)
38 | axiMaster.io.newRequest := axiReadRequestReg
39 | val axiAddrReg = RegInit(0.U(Width.Axi.addr))
40 | axiMaster.io.addr := axiAddrReg
41 |
42 | val lastPcReg = RegInit(zeroWord)
43 |
44 | // Fallback
45 | isPcNextReg := false.B
46 | axiReadRequestReg := false.B
47 | axiAddrReg := axiAddrReg
48 | io.instEnqueuePort.valid := false.B
49 | io.instEnqueuePort.bits := DontCare
50 | lastPcReg := lastPcReg
51 |
52 | switch(stateReg) {
53 | is(State.idle) {
54 | nextState := State.requestInst
55 | }
56 | is(State.requestInst) { // State Value: 1
57 | when(
58 | axiReady && io.instEnqueuePort.ready && !io.isFlush
59 | ) {
60 | nextState := State.waitInst
61 |
62 | isPcNextReg := true.B
63 | axiReadRequestReg := true.B
64 | axiAddrReg := io.pc
65 | lastPcReg := io.pc
66 | }.otherwise {
67 | nextState := State.requestInst
68 | }
69 | }
70 | is(State.waitInst) { // State Value: 2
71 | when(axiReadValid) {
72 | nextState := State.requestInst
73 | when(!io.isFlush) {
74 | io.instEnqueuePort.valid := true.B
75 | io.instEnqueuePort.bits.inst := axiData
76 | io.instEnqueuePort.bits.pcAddr := lastPcReg
77 | }
78 | }
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/src/frontend/bpu/RAS.scala:
--------------------------------------------------------------------------------
1 | package frontend.bpu
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import spec._
6 |
7 | //return address stack
8 | class RAS(
9 | entryNum: Int = Param.BPU.RAS.entryNum,
10 | addr: Int = spec.Width.Mem._addr)
11 | extends Module {
12 | val addrWidth = log2Ceil(addr)
13 | val pointerWidth = log2Ceil(entryNum)
14 | val io = IO(new Bundle {
15 | val push = Input(Bool())
16 | val pop = Input(Bool())
17 | val callAddr = Input(UInt(spec.Width.Mem.addr))
18 | val topAddr = Output(UInt(spec.Width.Mem.addr))
19 | val predictPush = Input(Bool())
20 | val predictPop = Input(Bool())
21 | val predictCallAddr = Input(UInt(spec.Width.Mem.addr))
22 | val predictError = Input(Bool())
23 | })
24 | // Data structure
25 | // use a Vec to act as a stack
26 | val lutram = RegInit(VecInit(Seq.fill(entryNum)(0.U(spec.Width.Mem.addr))))
27 | val predictLutram = RegInit(VecInit(Seq.fill(entryNum)(0.U(spec.Width.Mem.addr))))
28 |
29 | // Signal defines
30 | val newIndex = WireInit(0.U(pointerWidth.W))
31 | val readIndex = RegInit(0.U(pointerWidth.W))
32 |
33 | val predictNewIndex = WireInit(0.U(pointerWidth.W))
34 | val predictReadIndex = RegInit(0.U(pointerWidth.W))
35 |
36 | // Actually data
37 | // Index
38 | newIndex := readIndex + io.push - io.pop
39 | readIndex := newIndex
40 | // Data
41 | when(io.push) {
42 | lutram(newIndex) := io.callAddr
43 | }
44 |
45 | // predict data
46 | // Index
47 | predictNewIndex := predictReadIndex + io.predictPush - io.predictPop
48 | predictReadIndex := predictNewIndex
49 |
50 | // Data
51 | if (Param.isOverideRas) {
52 | when(io.predictPush) {
53 | predictLutram(predictNewIndex) := io.predictCallAddr
54 | }
55 | } else {
56 | when(io.predictPush) {
57 | lutram(predictNewIndex) := io.predictCallAddr
58 | }
59 | }
60 |
61 | // when branch predict error, reset ptr
62 | when(io.predictError) {
63 | predictNewIndex := newIndex
64 | if (Param.isOverideRas) {
65 | predictLutram := lutram
66 | }
67 | }
68 | // Output
69 | if (Param.isOverideRas) {
70 | // io.topAddr := Mux(io.predictError, lutram(readIndex), predictLutram(predictReadIndex))
71 | io.topAddr := predictLutram(predictReadIndex)
72 | } else {
73 | io.topAddr := lutram(predictReadIndex)
74 | }
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/src/src/frontend/bpu/bundles/BpuFtqMetaNdPort.scala:
--------------------------------------------------------------------------------
1 | package frontend.bpu.bundles
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import frontend.bpu.components.Bundles.TageMetaPort
6 | import spec._
7 |
8 | class BpuFtqMetaNdPort(
9 | ftbNway: Int = Param.BPU.FTB.nway)
10 | extends Bundle {
11 | val ftbHit = Bool()
12 | val ftbHitIndex = UInt(log2Ceil(ftbNway).W)
13 | val tageQueryMeta = new TageMetaPort
14 | }
15 |
16 | object BpuFtqMetaNdPort {
17 | def default = 0.U.asTypeOf(new BpuFtqMetaNdPort)
18 | }
19 |
--------------------------------------------------------------------------------
/src/src/frontend/bpu/bundles/FtqBranchMetaEntry.scala:
--------------------------------------------------------------------------------
1 | package frontend.bpu.bundles
2 |
3 | import chisel3._
4 | import chisel3.util.log2Ceil
5 | import spec._
6 | class FtqBranchMetaEntry(
7 | addr: Int = wordLength)
8 | extends Bundle {
9 | val ftbDirty = Bool()
10 | val jumpTargetAddr = UInt(addr.W)
11 | val fetchLastIdx = UInt(log2Ceil(Param.fetchInstMaxNum).W)
12 | }
13 |
14 | object FtqBranchMetaEntry {
15 | def default = 0.U.asTypeOf(new FtqBranchMetaEntry)
16 | }
17 |
--------------------------------------------------------------------------------
/src/src/frontend/bpu/bundles/TagePredictorUpdateInfoPort.scala:
--------------------------------------------------------------------------------
1 | package frontend.bpu.bundles
2 | import chisel3._
3 | import frontend.bpu.components.Bundles.TageMetaPort
4 |
5 | class TagePredictorUpdateInfoPort extends Bundle {
6 | val valid = Bool()
7 | val predictCorrect = Bool()
8 | val branchTaken = Bool()
9 | val isConditional = Bool()
10 | val tageOriginMeta = new TageMetaPort
11 | }
12 |
13 | object TagePredictorUpdateInfoPort {
14 | def default = 0.U.asTypeOf(new TagePredictorUpdateInfoPort)
15 | }
16 |
--------------------------------------------------------------------------------
/src/src/frontend/bpu/components/BasePredictor.scala:
--------------------------------------------------------------------------------
1 | package frontend.bpu.components
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import memory.VSimpleDualBRam
6 | import spec.{Param, Width}
7 |
8 | class BasePredictor(
9 | nway: Int = Param.BPU.FTB.nway,
10 | ctrWidth: Int = Param.BPU.TagePredictor.componentCtrWidth(0),
11 | tableDepth: Int = Param.BPU.TagePredictor.componentTableDepth(0),
12 | addr: Int = spec.Width.Mem._addr)
13 | extends Module {
14 | // param
15 | val tableDepthLog = log2Ceil(tableDepth)
16 |
17 | val io = IO(new Bundle {
18 | val pc = Input(UInt(Width.Reg.data))
19 | val isTaken = Output(Bool())
20 | val ctr = Output(UInt(ctrWidth.W)) // counter, use to show predictor state
21 |
22 | // Update
23 | val updateValid = Input(Bool())
24 | val updatePc = Input(UInt(addr.W))
25 | val isCtrInc = Input(Bool()) // if istaken from backend,counter inc 1
26 | val updateCtr = Input(UInt(ctrWidth.W))
27 | })
28 |
29 | // Query logic
30 | val queryIndex = Wire(UInt(tableDepthLog.W))
31 | val queryEntry = Wire(UInt(ctrWidth.W))
32 |
33 | queryIndex := io.pc(1 + tableDepthLog, 2)
34 | // base predictor ctrWidth == 2
35 |
36 | // 00-.weakly taken; 01->stronglty taken; 10-> strongly not taken' 11->weakly not taken
37 | io.isTaken := queryEntry(ctrWidth - 1) === 0.U
38 | io.ctr := queryEntry
39 |
40 | // update logic
41 | val updateIndex = Wire(UInt(tableDepthLog.W))
42 | val updateContent = Wire(UInt(ctrWidth.W))
43 |
44 | updateIndex := io.updatePc(tableDepthLog + 1, 2)
45 |
46 | // base predictor state ctr change when isCtrInc
47 | // 10 strongly not taken => 11 weakly not taken => 00 weakly taken => 01 strongly taken
48 | when(io.updateValid) {
49 | when(io.updateCtr === Cat(0.U(1.W), 1.U((ctrWidth - 1).W))) { // b01
50 | updateContent := Mux(io.isCtrInc, io.updateCtr, io.updateCtr - 1.U(ctrWidth.W))
51 | }.elsewhen(io.updateCtr === Cat(1.U(1.W), 0.U((ctrWidth - 1).W))) { // b10
52 | updateContent := Mux(io.isCtrInc, io.updateCtr + 1.U(ctrWidth.W), io.updateCtr)
53 | }.otherwise {
54 | updateContent := Mux(io.isCtrInc, io.updateCtr + 1.U(ctrWidth.W), io.updateCtr - 1.U(ctrWidth.W))
55 | }
56 | }.otherwise {
57 | updateContent := 0.U(ctrWidth.W)
58 | }
59 |
60 | val ctrRam = Module(
61 | new VSimpleDualBRam(
62 | tableDepth, // size
63 | ctrWidth // dataWidth
64 | )
65 | )
66 | ctrRam.io.readAddr := queryIndex
67 | queryEntry := ctrRam.io.dataOut
68 | ctrRam.io.isWrite := io.updateValid
69 | ctrRam.io.dataIn := updateContent
70 | ctrRam.io.writeAddr := updateIndex
71 | }
72 |
--------------------------------------------------------------------------------
/src/src/frontend/bpu/components/Bundles/FtbEntryNdPort.scala:
--------------------------------------------------------------------------------
1 | package frontend.bpu.components.Bundles
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import spec._
6 | class FtbEntryNdPort extends Bundle {
7 | val valid = Bool()
8 | val isCrossCacheline = Bool()
9 | val branchType = UInt(Param.BPU.BranchType.width.W)
10 |
11 | // Virtual tag, pc[1:0] is always 0, so not used in index or tag
12 | val tag = UInt(Param.BPU.FTB.tagWidth.W)
13 | val jumpPartialTargetAddr = UInt((spec.Width.Mem._addr - 2).W)
14 | val fetchLastIdx = UInt(log2Ceil(Param.fetchInstMaxNum).W) // fetchLastIdx + 1 = fetchLength
15 | // val fallThroughAddr = UInt(spec.Width.Mem.addr)
16 | }
17 |
18 | object FtbEntryNdPort {
19 | // val width =
20 | // 1 + 1 + 2 + spec.Width.Mem._addr - 2 - log2Ceil(Param.BPU.FTB.nset) + 2 * spec.Width.Mem._addr
21 | val width =
22 | 1 + 1 + Param.BPU.BranchType.width + log2Ceil(
23 | Param.fetchInstMaxNum
24 | ) + Param.BPU.FTB.tagWidth + spec.Width.Mem._addr - 2
25 | def default = 0.U.asTypeOf(new FtbEntryNdPort)
26 | }
27 |
--------------------------------------------------------------------------------
/src/src/frontend/bpu/components/Bundles/TageMetaPort.scala:
--------------------------------------------------------------------------------
1 | package frontend.bpu.components.Bundles
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import spec._
6 |
7 | class TageGhrInfo(
8 | tagComponentNum: Int = Param.BPU.TagePredictor.tagComponentNum,
9 | tagComponentTagWidth: Int = Param.BPU.TagePredictor.tagComponentTagWidth,
10 | phtAddrWidth: Int = log2Ceil(Param.BPU.TagePredictor.componentTableDepth(1)))
11 | extends Bundle {
12 | val checkPtr = UInt(Param.BPU.TagePredictor.ghrPtrWidth.W)
13 | val tagGhtHashs = Vec(tagComponentNum, UInt(phtAddrWidth.W))
14 | val tagTagHashCsr1s = Vec(tagComponentNum, UInt(tagComponentTagWidth.W))
15 | val tagTagHashCsr2s = Vec(tagComponentNum, UInt((tagComponentTagWidth - 1).W))
16 | }
17 |
18 |
19 | class TageMetaPort(
20 | tagComponentNum: Int = Param.BPU.TagePredictor.tagComponentNum,
21 | tagComponentTagWidth: Int = Param.BPU.TagePredictor.tagComponentTagWidth,
22 | phtAddrWidth: Int = log2Ceil(Param.BPU.TagePredictor.componentTableDepth(1)))
23 | extends Bundle {
24 | val providerId = UInt(log2Ceil(tagComponentNum + 1).W)
25 | val altProviderId = UInt(log2Ceil(tagComponentNum + 1).W)
26 | val isUseful = Bool()
27 | val providerCtrBits = Vec(tagComponentNum + 1, UInt(3.W))
28 | val tagPredictorQueryTags = Vec(tagComponentNum, UInt(tagComponentTagWidth.W))
29 | val tagPredictorOriginTags = Vec(tagComponentNum, UInt(tagComponentTagWidth.W))
30 | val tagPredictorHitIndexs = Vec(tagComponentNum, UInt(10.W))
31 | val tagPredictorUsefulBits = Vec(tagComponentNum, UInt(3.W))
32 | // global history Hash info
33 | val tageGhrInfo = new TageGhrInfo()
34 | }
35 |
36 | object TageMetaPort {
37 | def default = 0.U.asTypeOf(new TageMetaPort)
38 | }
39 |
--------------------------------------------------------------------------------
/src/src/frontend/bpu/utils/CsrHash.scala:
--------------------------------------------------------------------------------
1 | package frontend.bpu.utils
2 | import chisel3._
3 | import chisel3.util._
4 | import spec.Param
5 |
6 | // Implement GHR hash using a CSR (Circular Shifted Register)
7 | class CsrHash(
8 | inputLength: Int = 25,
9 | outputLength: Int = 10)
10 | extends Module {
11 | val io = IO(new Bundle {
12 | val dataUpdate = Input(Bool())
13 | val data = Input(UInt(inputLength.W))
14 | val hash = Output(UInt(outputLength.W))
15 | val isFixHash = Input(Bool())
16 | val isRecoverHash = Input(Bool())
17 | val originHash = Input(UInt(outputLength.W))
18 | })
19 |
20 | val csr = RegInit(0.U(outputLength.W))
21 | val nextCSR = WireDefault(0.U(outputLength.W))
22 |
23 | val residual = (inputLength - 1) % outputLength
24 | // nextCSR := Cat(csr(outputLength - 2, 0), csr(outputLength - 1) ^ io.data(0))
25 | // nextCSR(residual) := nextCSR(residual, residual) ^ io.data(inputLength - 1)
26 |
27 | if (Param.isSpeculativeGlobalHistory) {
28 | nextCSR := Mux(
29 | io.isRecoverHash,
30 | io.originHash,
31 | Mux(
32 | io.isFixHash,
33 | Cat(io.originHash(outputLength - 2, 0), io.originHash(outputLength - 1) ^ io.data(0)) ^ (io.data(
34 | inputLength - 1
35 | ) << residual).asUInt,
36 | Mux(
37 | io.dataUpdate,
38 | Cat(csr(outputLength - 2, 0), csr(outputLength - 1) ^ io.data(0)) ^ (io.data(
39 | inputLength - 1
40 | ) << residual).asUInt,
41 | csr
42 | )
43 | )
44 | )
45 | } else {
46 | // commit update
47 | nextCSR := Mux(
48 | io.dataUpdate,
49 | Cat(csr(outputLength - 2, 0), csr(outputLength - 1) ^ io.data(0)) ^ (io.data(
50 | inputLength - 1
51 | ) << residual).asUInt,
52 | csr
53 | )
54 | }
55 |
56 | // when(io.dataUpdate) {
57 | // csr := nextCSR
58 | // }
59 | csr := nextCSR
60 |
61 | io.hash := csr
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/src/src/frontend/bpu/utils/DebugCsrHash.scala:
--------------------------------------------------------------------------------
1 | package frontend.bpu.utils
2 | import chisel3._
3 | import chisel3.util._
4 | import spec.Param
5 |
6 | // Implement GHR hash using a CSR (Circular Shifted Register)
7 | class DebugCsrHash(
8 | inputLength: Int = 25,
9 | outputLength: Int = 10)
10 | extends Module {
11 | val io = IO(new Bundle {
12 | val dataUpdate = Input(Bool())
13 | val data = Input(UInt(inputLength.W))
14 | val hash = Output(UInt(outputLength.W))
15 | })
16 |
17 | val csr = RegInit(0.U(outputLength.W))
18 | val nextCSR = WireDefault(0.U(outputLength.W))
19 |
20 | val residual = (inputLength - 1) % outputLength
21 | // nextCSR := Cat(csr(outputLength - 2, 0), csr(outputLength - 1) ^ io.data(0))
22 | // nextCSR(residual) := nextCSR(residual, residual) ^ io.data(inputLength - 1)
23 |
24 | // commit update
25 | nextCSR := Mux(
26 | io.dataUpdate,
27 | Cat(csr(outputLength - 2, 0), csr(outputLength - 1) ^ io.data(0)) ^ (io.data(
28 | inputLength - 1
29 | ) << residual).asUInt,
30 | csr
31 | )
32 |
33 | // when(io.dataUpdate) {
34 | // csr := nextCSR
35 | // }
36 | csr := nextCSR
37 |
38 | io.hash := csr
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/src/src/frontend/bundles/BpuFtqPort.scala:
--------------------------------------------------------------------------------
1 | package frontend.bundles
2 |
3 | import chisel3._
4 | import frontend.bpu.bundles.BpuFtqMetaNdPort
5 | class BpuFtqPort extends Bundle {
6 | val ftqP0 = Input(new FtqBlockBundle)
7 | val ftqP1 = Input(new FtqBlockBundle)
8 | val bpuQueryMeta = Input(new BpuFtqMetaNdPort)
9 | val ftqFull = Output(Bool())
10 | val ftqBpuTrainMeta = Output(new FtqBpuMetaPort)
11 | // pc redirect
12 | val bpuRedirectValid = Input(Bool())
13 | }
14 |
--------------------------------------------------------------------------------
/src/src/frontend/bundles/BranchTakenMetaBundle.scala:
--------------------------------------------------------------------------------
1 | package frontend.bundles
2 |
3 | import chisel3._
4 |
5 | class BranchTakenMetaBundle extends Bundle {
6 | val branchType = UInt(2.W)
7 | val isTaken = Bool()
8 | val predictedTaken = Bool() // Comes from bpu
9 | }
10 |
--------------------------------------------------------------------------------
/src/src/frontend/bundles/CommitFtqTrainNdPort.scala:
--------------------------------------------------------------------------------
1 | package frontend.bundles
2 |
3 | import chisel3._
4 | import spec.Param
5 |
6 | class CommitFtqTrainNdPort extends Bundle {
7 | // val bitMask = Vec(Param.commitNum, Bool())
8 | val isTrainValid = Bool()
9 | val ftqId = UInt(Param.BPU.Width.id)
10 | val branchTakenMeta = new BranchTakenMetaBundle
11 | }
12 |
13 | object CommitFtqTrainNdPort {
14 | def default = 0.U.asTypeOf(new CommitFtqTrainNdPort)
15 | }
16 |
--------------------------------------------------------------------------------
/src/src/frontend/bundles/ExeFtqPort.scala:
--------------------------------------------------------------------------------
1 | package frontend.bundles
2 | import chisel3._
3 | import chisel3.util.log2Ceil
4 | import spec.Param
5 | class ExeFtqPort extends Bundle {
6 | val queryPcBundle = new QueryPcBundle
7 | val feedBack = Input(new ExeFtqFeedBackNdPort)
8 | }
9 |
10 | class QueryPcBundle extends Bundle {
11 | val ftqId = Input(UInt(spec.Param.BPU.ftqPtrWidth.W))
12 | val pc = Output(UInt(spec.Width.Mem.addr))
13 | }
14 |
15 | class ExeCommitFtqNdPort extends Bundle {
16 | val ftqMetaUpdateValid = Bool()
17 | val ftqMetaUpdateFtbDirty = Bool()
18 | val ftqMetaUpdateJumpTarget = UInt(spec.Width.Mem.addr)
19 | val fetchLastIdx = UInt(log2Ceil(Param.fetchInstMaxNum).W)
20 | val ftqMetaUpdateFallThrough = UInt(spec.Width.Mem.addr)
21 | val ftqUpdateMetaId = UInt(Param.BPU.Width.id)
22 | }
23 | class ExeFtqFeedBackNdPort extends Bundle {
24 | val commitBundle = new ExeCommitFtqNdPort
25 | val fixGhrBundle = new ExeFtqFixGhrBundle
26 | }
27 |
--------------------------------------------------------------------------------
/src/src/frontend/bundles/FetchCsrNdPort.scala:
--------------------------------------------------------------------------------
1 | package frontend.bundles
2 |
3 | import chisel3._
4 | import control.csrBundles.{CrmdBundle, DmwBundle}
5 |
6 | class FetchCsrNdPort extends Bundle {
7 | val crmd = new CrmdBundle
8 | val dmw = Vec(2, new DmwBundle)
9 | }
10 |
--------------------------------------------------------------------------------
/src/src/frontend/bundles/FtqBlockBundle.scala:
--------------------------------------------------------------------------------
1 | package frontend.bundles
2 |
3 | import chisel3._
4 | import chisel3.experimental.BundleLiterals.AddBundleLiteralConstructor
5 | import chisel3.util._
6 | import spec._
7 | class FtqBlockBundle extends Bundle {
8 | val isValid = Bool()
9 | val isCrossCacheline = Bool()
10 | val fetchLastIdx = UInt(log2Ceil(Param.fetchInstMaxNum).W)
11 | val predictTaken = Bool()
12 | val predictValid = Bool()
13 | val startPc = UInt(spec.Width.Mem.addr)
14 | }
15 |
16 | object FtqBlockBundle {
17 | def default = (new FtqBlockBundle).Lit(
18 | _.isValid -> false.B,
19 | _.isCrossCacheline -> false.B,
20 | _.fetchLastIdx -> 0.U(log2Ceil(Param.fetchInstMaxNum).W),
21 | _.predictTaken -> false.B,
22 | _.predictValid -> false.B,
23 | _.startPc -> 0.U(spec.Width.Mem.addr)
24 | )
25 | }
26 |
--------------------------------------------------------------------------------
/src/src/frontend/bundles/FtqBpuMetaPort.scala:
--------------------------------------------------------------------------------
1 | package frontend.bundles
2 | import chisel3._
3 | import chisel3.util._
4 | import frontend.bpu.components.Bundles.{TageGhrInfo, TageMetaPort}
5 | import spec._
6 |
7 | class BranchAddrBundle extends Bundle {
8 | val startPc = UInt(spec.Width.Mem.addr)
9 | val jumpPartialTargetAddr = UInt((spec.Width.Mem._addr - 2).W)
10 | val fetchLastIdx = UInt(log2Ceil(Param.fetchInstMaxNum).W)
11 | // val fallThroughAddr = UInt(spec.Width.Mem.addr)
12 | }
13 |
14 | class ExeFtqFixGhrBundle extends Bundle {
15 | val isExeFixValid = Bool()
16 | val exeFixIsTaken = Bool()
17 | }
18 | class GhrUpdateSignalBundle extends Bundle {
19 | val exeFixBundle = new ExeFtqFixGhrBundle
20 | val isPredecoderFixGhr = Bool()
21 | val isPredecoderBranchTaken = Bool()
22 | }
23 | class FtqBpuMetaPort(
24 | ftbNway: Int = Param.BPU.FTB.nway,
25 | addr: Int = wordLength)
26 | extends Bundle {
27 | val valid = Bool()
28 | val ftbHit = Bool()
29 | val ftbHitIndex = UInt(log2Ceil(ftbNway).W)
30 | val ftbDirty = Bool()
31 | val isCrossCacheline = Bool()
32 |
33 | val tageOriginMeta = new TageMetaPort
34 |
35 | // Backend Decode Info
36 | val branchTakenMeta = new BranchTakenMetaBundle
37 |
38 | // FTB train meta
39 | val branchAddrBundle = new BranchAddrBundle
40 |
41 | // train meta
42 | val ghrUpdateSignalBundle = new GhrUpdateSignalBundle // global history register
43 | val tageGhrInfo = new TageGhrInfo()
44 | }
45 |
46 | object FtqBpuMetaPort {
47 | def default = 0.U.asTypeOf(new FtqBpuMetaPort)
48 | }
49 |
--------------------------------------------------------------------------------
/src/src/frontend/bundles/FtqIFNdPort.scala:
--------------------------------------------------------------------------------
1 | package frontend.bundles
2 | import chisel3._
3 | import spec._
4 | class FtqIFNdPort extends Bundle {
5 | val ftqBlockBundle = new FtqBlockBundle
6 | val redirect = Bool()
7 | val ftqId = UInt(Param.BPU.ftqPtrWidth.W)
8 | }
9 |
10 | object FtqIFNdPort {
11 | def default = 0.U.asTypeOf(new FtqIFNdPort)
12 | }
13 |
--------------------------------------------------------------------------------
/src/src/frontend/bundles/ICacheAccessPort.scala:
--------------------------------------------------------------------------------
1 | package frontend.bundles
2 |
3 | import chisel3._
4 |
5 | class ICacheAccessPort extends Bundle {
6 | val req = new ICacheRequestHandshakePort
7 | val res = Output(new InstMemResponseNdPort)
8 | }
9 |
--------------------------------------------------------------------------------
/src/src/frontend/bundles/ICacheRequestHandshakePort.scala:
--------------------------------------------------------------------------------
1 | package frontend.bundles
2 | import chisel3._
3 |
4 | class ICacheRequestHandshakePort extends Bundle {
5 | val client = Input(new ICacheRequestNdPort)
6 | val isReady = Output(Bool())
7 | }
8 |
--------------------------------------------------------------------------------
/src/src/frontend/bundles/ICacheRequestNdPort.scala:
--------------------------------------------------------------------------------
1 | package frontend.bundles
2 |
3 | import chisel3._
4 | import chisel3.experimental.BundleLiterals._
5 | import spec._
6 |
7 | class ICacheRequestNdPort extends Bundle {
8 | val isValid = Bool()
9 | val addr = UInt(Width.Mem.addr)
10 | // when muti fetch,mem addr must ignore addr of fetchWidth tag; mem data index (log(fetchNum) bits) default to 0
11 | val isCached = Bool()
12 | }
13 |
14 | object ICacheRequestNdPort {
15 | def default = (new ICacheRequestNdPort).Lit(
16 | _.isValid -> false.B,
17 | _.addr -> zeroWord,
18 | _.isCached -> false.B
19 | )
20 | }
21 |
--------------------------------------------------------------------------------
/src/src/frontend/bundles/InstMemResponseNdPort.scala:
--------------------------------------------------------------------------------
1 | package frontend.bundles
2 |
3 | import chisel3._
4 | import spec._
5 |
6 | class InstMemResponseNdPort extends Bundle {
7 | val isComplete = Bool()
8 | val isFailed = Bool()
9 | val read = new Bundle {
10 | val dataVec = Vec(Param.Count.ICache.dataPerLine, UInt(Width.Mem.data))
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/src/frontend/bundles/PredecoderResultNdPort.scala:
--------------------------------------------------------------------------------
1 | package frontend.bundles
2 |
3 | import chisel3._
4 |
5 | class PreDecoderResultNdPort extends Bundle {
6 | val isBranch = Bool()
7 | val isJump = Bool()
8 | val isImmJump = Bool()
9 | val isCall = Bool()
10 | val isRet = Bool()
11 | val jumpTargetAddr = UInt(spec.Width.Reg.data)
12 | }
13 |
14 | object PreDecoderResultNdPort {
15 | def default = 0.U.asTypeOf(new PreDecoderResultNdPort)
16 | }
17 |
--------------------------------------------------------------------------------
/src/src/frontend/fetch/InstReqStage.scala:
--------------------------------------------------------------------------------
1 | package frontend.fetch
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import common.BaseStage
6 | import frontend.bundles.{FtqBlockBundle, ICacheRequestHandshakePort, ICacheRequestNdPort}
7 | import spec.{Param, Width}
8 |
9 | class InstReqNdPort extends Bundle {
10 | val translatedMemReq = new ICacheRequestNdPort
11 | val ftqBlock = new FtqBlockBundle
12 | val ftqId = UInt(Param.BPU.ftqPtrWidth.W)
13 | val exception = Valid(UInt(Width.Csr.exceptionIndex))
14 | val isRedirect = Bool()
15 | }
16 |
17 | object InstReqNdPort {
18 | def default: InstReqNdPort = 0.U.asTypeOf(new InstReqNdPort)
19 | }
20 |
21 | class InstReqPeerPort extends Bundle {
22 | val memReq = Flipped(new ICacheRequestHandshakePort)
23 | }
24 |
25 | class InstReqStage
26 | extends BaseStage(
27 | new InstReqNdPort,
28 | new InstResNdPort,
29 | InstReqNdPort.default,
30 | Some(new InstReqPeerPort)
31 | ) {
32 | val peer = io.peer.get
33 | val out = resultOutReg.bits
34 |
35 | val excpValid = WireDefault(selectedIn.exception.valid)
36 |
37 | // Fallback output
38 | out.ftqBlock := selectedIn.ftqBlock
39 | out.ftqId := selectedIn.ftqId
40 | out.exception := selectedIn.exception
41 |
42 | // Fallback peer
43 | peer.memReq.client := selectedIn.translatedMemReq
44 | when(selectedIn.isRedirect) {
45 | isComputed := true.B
46 | }.elsewhen(selectedIn.translatedMemReq.isValid && (!excpValid)) {
47 | when(io.out.ready) {
48 | // Whether memory request is submitted
49 | isComputed := peer.memReq.isReady
50 |
51 | peer.memReq.client.isValid := true.B
52 | peer.memReq.client.addr := selectedIn.translatedMemReq.addr
53 | peer.memReq.client.isCached := selectedIn.translatedMemReq.isCached
54 | }.otherwise {
55 | isComputed := false.B
56 | }
57 |
58 | // Submit result
59 | resultOutReg.valid := isComputed
60 | }.elsewhen(excpValid) {
61 | // when pc is not aline or has a tlb excption, do not send mem request but still submit to backend to solve
62 | peer.memReq.client.isValid := false.B
63 | isComputed := true.B
64 | resultOutReg.valid := isComputed
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/src/memory/BRam.scala:
--------------------------------------------------------------------------------
1 | package memory
2 |
3 | import chisel3._
4 | import chisel3.util._
5 |
6 | class SingleBRam(size: Int, dataWidth: Int) extends Module {
7 | val addrWidth = log2Ceil(size)
8 |
9 | val io = IO(new Bundle {
10 | val isWrite = Input(Bool())
11 | val addr = Input(UInt(addrWidth.W))
12 | val dataIn = Input(UInt(dataWidth.W))
13 | val dataOut = Output(UInt(dataWidth.W))
14 | })
15 |
16 | val data = RegInit(VecInit(Seq.fill(size)(0.U(dataWidth.W))))
17 |
18 | // Read
19 | io.dataOut := RegNext(data(io.addr))
20 |
21 | // Write
22 | when(io.isWrite) {
23 | data(io.addr) := io.dataIn
24 | }
25 | }
26 |
27 | class SimpleDualBRam(size: Int, dataWidth: Int) extends Module {
28 | val addrWidth = log2Ceil(size)
29 |
30 | val io = IO(new Bundle {
31 | val isWrite = Input(Bool())
32 | val readAddr = Input(UInt(addrWidth.W))
33 | val writeAddr = Input(UInt(addrWidth.W))
34 | val dataIn = Input(UInt(dataWidth.W))
35 | val dataOut = Output(UInt(dataWidth.W))
36 | })
37 |
38 | val data = RegInit(VecInit(Seq.fill(size)(0.U(dataWidth.W))))
39 |
40 | // Read
41 | io.dataOut := RegNext(data(io.readAddr), 0.U)
42 |
43 | // Write
44 | when(io.isWrite) {
45 | data(io.writeAddr) := io.dataIn
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/src/memory/LutRam.scala:
--------------------------------------------------------------------------------
1 | package memory
2 |
3 | import chisel3._
4 | import chisel3.util._
5 |
6 | class SingleLutRam(size: Int, dataWidth: Int) extends Module {
7 | val addrWidth = log2Ceil(size)
8 |
9 | val io = IO(new Bundle {
10 | val isWrite = Input(Bool())
11 | val addr = Input(UInt(addrWidth.W))
12 | val dataIn = Input(UInt(dataWidth.W))
13 | val dataOut = Output(UInt(dataWidth.W))
14 | })
15 |
16 | val ram = Mem(size, UInt(dataWidth.W))
17 |
18 | // Read
19 | io.dataOut := ram.read(io.addr)
20 |
21 | // Write
22 | when(io.isWrite) {
23 | ram(io.addr) := io.dataIn
24 | }
25 | }
26 |
27 | class SimpleDualLutRam(size: Int, dataWidth: Int) extends Module {
28 | val addrWidth = log2Ceil(size)
29 |
30 | val io = IO(new Bundle {
31 | val isWrite = Input(Bool())
32 | val readAddr = Input(UInt(addrWidth.W))
33 | val writeAddr = Input(UInt(addrWidth.W))
34 | val dataIn = Input(UInt(dataWidth.W))
35 | val dataOut = Output(UInt(dataWidth.W))
36 | })
37 |
38 | val ram = Mem(size, UInt(dataWidth.W))
39 |
40 | // Read
41 | io.dataOut := ram.read(io.readAddr)
42 |
43 | // Write
44 | when(io.isWrite) {
45 | ram(io.writeAddr) := io.dataIn
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/src/memory/SimpleRam.scala:
--------------------------------------------------------------------------------
1 | package memory
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import memory.bundles.{SimpleRamReadPort, SimpleRamWriteNdPort}
6 |
7 | class SimpleRam(size: Int, dataWidth: Int, isDebug: Boolean = false, debugWriteNum: Int = 0) extends Module {
8 | val addrWidth = log2Ceil(size)
9 |
10 | val io = IO(new Bundle {
11 | val readPort = new SimpleRamReadPort(addrWidth, dataWidth)
12 | val writePort = Input(new SimpleRamWriteNdPort(addrWidth, dataWidth))
13 | val debugPorts =
14 | if (isDebug)
15 | Some(
16 | Vec(debugWriteNum, Input(new SimpleRamWriteNdPort(addrWidth, dataWidth)))
17 | )
18 | else None
19 | })
20 |
21 | val data = RegInit(VecInit(Seq.fill(size)(0.U(dataWidth.W))))
22 | data := data
23 |
24 | // Read
25 | io.readPort.data := data(io.readPort.addr)
26 |
27 | // Write
28 | when(io.writePort.en) {
29 | data(io.writePort.addr) := io.writePort.data
30 | }
31 |
32 | // Debug: Prepare RAM
33 | io.debugPorts match {
34 | case Some(ports) =>
35 | ports.foreach { port =>
36 | when(port.en) {
37 | data(port.addr) := port.data
38 | }
39 | }
40 | case None =>
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/src/memory/bundles/CacheMaintenanceControlNdPort.scala:
--------------------------------------------------------------------------------
1 | package memory.bundles
2 |
3 | import chisel3._
4 |
5 | class CacheMaintenanceControlNdPort extends Bundle {
6 | val isL1Valid = Bool() // Maintenance operation on L1 data/instruction cache
7 | val isL2Valid = Bool() // Maintenance operation on L2 cache
8 | val isInit = Bool() // Maintenance for initialize cache
9 | val isCoherentByIndex = Bool() // Maintenance for keeping coherent by index
10 | val isCoherentByHit = Bool() // Maintenance for keeping coherent only when hit
11 | }
12 |
13 | object CacheMaintenanceControlNdPort {
14 | def default = 0.U.asTypeOf(new CacheMaintenanceControlNdPort)
15 | }
16 |
--------------------------------------------------------------------------------
/src/src/memory/bundles/CacheMaintenanceHandshakePort.scala:
--------------------------------------------------------------------------------
1 | package memory.bundles
2 |
3 | import chisel3._
4 |
5 | class CacheMaintenanceHandshakePort extends Bundle {
6 | val client = Input(new CacheMaintenanceNdPort)
7 | val isReady = Output(Bool())
8 | }
9 |
--------------------------------------------------------------------------------
/src/src/memory/bundles/CacheMaintenanceNdPort.scala:
--------------------------------------------------------------------------------
1 | package memory.bundles
2 |
3 | import chisel3._
4 | import spec._
5 |
6 | class CacheMaintenanceNdPort extends Bundle {
7 | val control = new CacheMaintenanceControlNdPort
8 | val addr = UInt(Width.Mem.addr) // Maintenance physical address
9 | }
10 |
--------------------------------------------------------------------------------
/src/src/memory/bundles/ICacheStatusTagBundle.scala:
--------------------------------------------------------------------------------
1 | package memory.bundles
2 |
3 | import chisel3._
4 | import spec._
5 |
6 | class ICacheStatusTagBundle extends Bundle {
7 | val isValid = Bool()
8 | val tag = UInt(Param.Width.ICache.tag)
9 | }
10 |
11 | object ICacheStatusTagBundle {
12 | val width = 1 + Param.Width.ICache._tag
13 | }
14 |
--------------------------------------------------------------------------------
/src/src/memory/bundles/MemAccessPort.scala:
--------------------------------------------------------------------------------
1 | package memory.bundles
2 |
3 | import chisel3._
4 |
5 | class MemAccessPort extends Bundle {
6 | val req = new MemRequestHandshakePort
7 | val res = Output(new MemResponseNdPort)
8 | }
9 |
--------------------------------------------------------------------------------
/src/src/memory/bundles/MemRequestHandshakePort.scala:
--------------------------------------------------------------------------------
1 | package memory.bundles
2 |
3 | import chisel3._
4 | import pipeline.common.bundles.MemRequestNdPort
5 |
6 | class MemRequestHandshakePort extends Bundle {
7 | val client = Input(new MemRequestNdPort)
8 | val isReady = Output(Bool())
9 | }
10 |
--------------------------------------------------------------------------------
/src/src/memory/bundles/MemResponseNdPort.scala:
--------------------------------------------------------------------------------
1 | package memory.bundles
2 |
3 | import chisel3._
4 | import spec._
5 |
6 | class MemResponseNdPort extends Bundle {
7 | val isComplete = Bool()
8 | val isFailed = Bool()
9 | val read = new Bundle {
10 | val data = UInt(Width.Mem.data)
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/src/memory/bundles/SimpleRamReadPort.scala:
--------------------------------------------------------------------------------
1 | package memory.bundles
2 |
3 | import chisel3._
4 |
5 | class SimpleRamReadPort(addrWidth: Int, dataWidth: Int) extends Bundle {
6 | val addr = Input(UInt(addrWidth.W))
7 | val data = Output(UInt(dataWidth.W))
8 | }
9 |
--------------------------------------------------------------------------------
/src/src/memory/bundles/SimpleRamWriteNdPort.scala:
--------------------------------------------------------------------------------
1 | package memory.bundles
2 |
3 | import chisel3._
4 |
5 | class SimpleRamWriteNdPort(addrWidth: Int, dataWidth: Int) extends Bundle {
6 | val en = Bool()
7 | val addr = UInt(addrWidth.W)
8 | val data = UInt(dataWidth.W)
9 | }
10 |
--------------------------------------------------------------------------------
/src/src/memory/bundles/StatusTagBundle.scala:
--------------------------------------------------------------------------------
1 | package memory.bundles
2 |
3 | import chisel3._
4 | import spec._
5 |
6 | class StatusTagBundle extends Bundle {
7 | val isValid = Bool()
8 | val isDirty = Bool()
9 | val tag = UInt(Param.Width.DCache.tag)
10 | }
11 |
12 | object StatusTagBundle {
13 | val width = 2 + Param.Width.DCache._tag
14 | }
15 |
--------------------------------------------------------------------------------
/src/src/memory/bundles/TlbCompareEntryBundle.scala:
--------------------------------------------------------------------------------
1 | package memory.bundles
2 |
3 | import chisel3._
4 | import chisel3.experimental.BundleLiterals._
5 | import spec._
6 |
7 | class TlbCompareEntryBundle extends Bundle {
8 | val isExisted = Bool()
9 | val asId = UInt(Width.Tlb.asid)
10 | val isGlobal = Bool()
11 | val pageSize = UInt(Width.Tlb.ps)
12 | val virtPageNum = UInt(Width.Tlb.vppn)
13 | }
14 |
15 | object TlbCompareEntryBundle {
16 | def default = (new TlbCompareEntryBundle).Lit(
17 | _.isExisted -> false.B,
18 | _.asId -> 0.U,
19 | _.isGlobal -> false.B,
20 | _.pageSize -> 0.U,
21 | _.virtPageNum -> 0.U
22 | )
23 | }
24 |
--------------------------------------------------------------------------------
/src/src/memory/bundles/TlbCsrWriteNdPort.scala:
--------------------------------------------------------------------------------
1 | package memory.bundles
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import control.csrBundles.{AsidBundle, TlbehiBundle, TlbeloBundle, TlbidxBundle}
6 |
7 | class TlbCsrWriteNdPort extends Bundle {
8 | val tlbidx = Valid(new TlbidxBundle)
9 | val tlbehi = Valid(new TlbehiBundle)
10 | val tlbeloVec = Vec(2, Valid(new TlbeloBundle))
11 | val asId = Valid(new AsidBundle)
12 | }
13 |
14 | object TlbCsrWriteNdPort {
15 | def default = 0.U.asTypeOf(new TlbCsrWriteNdPort)
16 | }
17 |
--------------------------------------------------------------------------------
/src/src/memory/bundles/TlbEntryBundle.scala:
--------------------------------------------------------------------------------
1 | package memory.bundles
2 |
3 | import chisel3._
4 | import chisel3.experimental.BundleLiterals._
5 | import chisel3.experimental.VecLiterals._
6 |
7 | class TlbEntryBundle extends Bundle {
8 | val compare = new TlbCompareEntryBundle
9 | val trans = Vec(2, new TlbTransEntryBundle)
10 | }
11 |
12 | object TlbEntryBundle {
13 | def default = (new TlbEntryBundle).Lit(
14 | _.compare -> TlbCompareEntryBundle.default,
15 | _.trans -> Vec.Lit(TlbTransEntryBundle.default, TlbTransEntryBundle.default)
16 | )
17 | }
18 |
--------------------------------------------------------------------------------
/src/src/memory/bundles/TlbMaintenanceNdPort.scala:
--------------------------------------------------------------------------------
1 | package memory.bundles
2 |
3 | import chisel3._
4 | import chisel3.experimental.BundleLiterals._
5 | import spec._
6 |
7 | class TlbMaintenanceNdPort extends Bundle {
8 | val isInvalidate = Bool()
9 | val isSearch = Bool()
10 | val isRead = Bool()
11 | val isWrite = Bool()
12 | val isFill = Bool()
13 | val virtAddr = UInt(Width.Mem.addr)
14 | val invalidateInst = UInt(Width.Tlb.op)
15 | val registerAsid = UInt(Width.Csr.asid)
16 | }
17 |
18 | object TlbMaintenanceNdPort {
19 | def default = (new TlbMaintenanceNdPort).Lit(
20 | _.isInvalidate -> false.B,
21 | _.isSearch -> false.B,
22 | _.isRead -> false.B,
23 | _.isWrite -> false.B,
24 | _.isFill -> false.B,
25 | _.registerAsid -> 0.U(Width.Csr.asid),
26 | _.virtAddr -> 0.U(Width.Mem.addr),
27 | _.invalidateInst -> 0.U(Width.Tlb.op)
28 | )
29 | }
30 |
--------------------------------------------------------------------------------
/src/src/memory/bundles/TlbTransEntryBundle.scala:
--------------------------------------------------------------------------------
1 | package memory.bundles
2 |
3 | import chisel3._
4 | import chisel3.experimental.BundleLiterals._
5 | import spec._
6 |
7 | class TlbTransEntryBundle extends Bundle {
8 | val isValid = Bool()
9 | val isDirty = Bool()
10 | val mat = UInt(2.W)
11 | val plv = UInt(2.W)
12 | val physPageNum = UInt(Width.Tlb.ppn)
13 | }
14 |
15 | object TlbTransEntryBundle {
16 | def default = (new TlbTransEntryBundle).Lit(
17 | _.isValid -> false.B,
18 | _.isDirty -> false.B,
19 | _.mat -> 0.U,
20 | _.plv -> 0.U,
21 | _.physPageNum -> 0.U
22 | )
23 | }
24 |
--------------------------------------------------------------------------------
/src/src/memory/bundles/TlbTransPort.scala:
--------------------------------------------------------------------------------
1 | package memory.bundles
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import memory.enums.TlbMemType
6 | import spec._
7 |
8 | class TlbTransPort extends Bundle {
9 | val isValid = Input(Bool())
10 | val virtAddr = Input(UInt(Width.Mem.addr))
11 | val memType = Input(TlbMemType())
12 | val physAddr = Output(UInt(Width.Mem.addr))
13 | val isNotCached = Output(Bool())
14 | val exception = Valid(UInt(Width.Csr.exceptionIndex))
15 | }
16 |
--------------------------------------------------------------------------------
/src/src/memory/bundles/TransExceptionCsrNdPort.scala:
--------------------------------------------------------------------------------
1 | package memory.bundles
2 |
3 | import chisel3._
4 | import spec._
5 |
6 | class TransExceptionCsrNdPort extends Bundle {
7 | val vppn = UInt(Width.Tlb.vppn)
8 | }
9 |
10 | object TransExceptionCsrNdPort {
11 | def default = 0.U.asTypeOf(new TransExceptionCsrNdPort)
12 | }
13 |
--------------------------------------------------------------------------------
/src/src/memory/enums/DCacheState.scala:
--------------------------------------------------------------------------------
1 | package memory.enums
2 |
3 | import chisel3.ChiselEnum
4 |
5 | object DCacheState extends ChiselEnum {
6 | val ready, refillForRead, refillForWrite, onlyWb, maintenanceInit, maintenanceHit, maintenanceOne, maintenanceAll =
7 | Value
8 | }
9 |
--------------------------------------------------------------------------------
/src/src/memory/enums/ICacheState.scala:
--------------------------------------------------------------------------------
1 | package memory.enums
2 |
3 | import chisel3.ChiselEnum
4 |
5 | object ICacheState extends ChiselEnum {
6 | val ready, refillForRead, maintenanceAll, maintenanceHit, maintenanceOne = Value
7 | }
8 |
--------------------------------------------------------------------------------
/src/src/memory/enums/TlbInstType.scala:
--------------------------------------------------------------------------------
1 | package memory.enums
2 |
3 | import chisel3.ChiselEnum
4 |
5 | object TlbInstType extends ChiselEnum {
6 | val search, read, write, fill, invalid = Value
7 | }
8 |
--------------------------------------------------------------------------------
/src/src/memory/enums/TlbMemType.scala:
--------------------------------------------------------------------------------
1 | package memory.enums
2 |
3 | import chisel3.ChiselEnum
4 |
5 | object TlbMemType extends ChiselEnum {
6 | val fetch, load, store = Value
7 | }
8 |
--------------------------------------------------------------------------------
/src/src/memory/enums/UncachedAgentState.scala:
--------------------------------------------------------------------------------
1 | package memory.enums
2 |
3 | import chisel3.ChiselEnum
4 |
5 | object UncachedAgentState extends ChiselEnum {
6 | val ready, waitReady, waitRes = Value
7 | }
8 |
--------------------------------------------------------------------------------
/src/src/pipeline/common/bundles/CacheMaintenanceInstNdPort.scala:
--------------------------------------------------------------------------------
1 | package pipeline.common.bundles
2 |
3 | import chisel3._
4 | import memory.bundles.CacheMaintenanceControlNdPort
5 | import pipeline.common.enums.CacheMaintenanceTargetType
6 |
7 | class CacheMaintenanceInstNdPort extends Bundle {
8 | val target = CacheMaintenanceTargetType()
9 | val control = new CacheMaintenanceControlNdPort
10 | }
11 |
--------------------------------------------------------------------------------
/src/src/pipeline/common/bundles/DifftestLoadNdPort.scala:
--------------------------------------------------------------------------------
1 | package pipeline.common.bundles
2 |
3 | import chisel3._
4 | import chisel3.experimental.BundleLiterals.AddBundleLiteralConstructor
5 |
6 | class DifftestLoadNdPort extends Bundle {
7 | val en = UInt(8.W) // {2'b0, inst_ll_w, inst_ld_w, inst_ld_hu, inst_ld_h, inst_ld_bu, inst_ld_b}
8 | val vaddr = UInt(32.W)
9 | val paddr = UInt(32.W)
10 | }
11 |
12 | object DifftestLoadNdPort {
13 | def default = (new DifftestLoadNdPort).Lit(
14 | _.en -> 0.U,
15 | _.vaddr -> 0.U,
16 | _.paddr -> 0.U
17 | )
18 | }
19 |
--------------------------------------------------------------------------------
/src/src/pipeline/common/bundles/DifftestStoreNdPort.scala:
--------------------------------------------------------------------------------
1 | package pipeline.common.bundles
2 |
3 | import chisel3._
4 | import chisel3.experimental.BundleLiterals.AddBundleLiteralConstructor
5 |
6 | class DifftestStoreNdPort extends Bundle {
7 | val en = UInt(8.W) // {4'b0, ds_llbit && inst_sc_w, inst_st_w, inst_st_h, inst_st_b}
8 | val vaddr = UInt(32.W)
9 | val paddr = UInt(32.W)
10 | val data = UInt(32.W)
11 | }
12 |
13 | object DifftestStoreNdPort {
14 | def default = (new DifftestStoreNdPort).Lit(
15 | _.en -> 0.U,
16 | _.vaddr -> 0.U,
17 | _.paddr -> 0.U,
18 | _.data -> 0.U
19 | )
20 | }
21 |
--------------------------------------------------------------------------------
/src/src/pipeline/common/bundles/DifftestTlbFillNdPort.scala:
--------------------------------------------------------------------------------
1 | package pipeline.common.bundles
2 |
3 | import chisel3._
4 | import chisel3.experimental.BundleLiterals.AddBundleLiteralConstructor
5 | import spec._
6 |
7 | class DifftestTlbFillNdPort extends Bundle {
8 | val valid = Bool()
9 | val fillIndex = UInt(Width.Reg.addr)
10 | }
11 |
12 | object DifftestTlbFillNdPort {
13 | def default = (new DifftestTlbFillNdPort).Lit(
14 | _.valid -> false.B,
15 | _.fillIndex -> 0.U
16 | )
17 | }
18 |
--------------------------------------------------------------------------------
/src/src/pipeline/common/bundles/FetchInstInfoBundle.scala:
--------------------------------------------------------------------------------
1 | package pipeline.common.bundles
2 |
3 | import chisel3._
4 | import chisel3.experimental.BundleLiterals._
5 | import spec._
6 |
7 | class FetchInstInfoBundle extends Bundle {
8 | val pcAddr = UInt(Width.Reg.data)
9 | val inst = UInt(Width.inst)
10 | val ftqInfo = new FtqInfoBundle
11 | val exceptionValid = Bool()
12 | val exception = UInt(Width.Csr.exceptionIndex)
13 | }
14 |
15 | object FetchInstInfoBundle {
16 | def default = (new FetchInstInfoBundle).Lit(
17 | _.pcAddr -> zeroWord,
18 | _.inst -> zeroWord,
19 | _.exceptionValid -> false.B,
20 | _.exception -> 0.U,
21 | _.ftqInfo -> FtqInfoBundle.default
22 | )
23 | }
24 |
--------------------------------------------------------------------------------
/src/src/pipeline/common/bundles/FtqInfoBundle.scala:
--------------------------------------------------------------------------------
1 | package pipeline.common.bundles
2 |
3 | import chisel3._
4 | import spec._
5 | import chisel3.util._
6 |
7 | class FtqInfoBundle extends Bundle {
8 | val isLastInBlock = Bool()
9 | val ftqId = UInt(Param.BPU.Width.id)
10 | val idxInBlock = UInt(log2Ceil(Param.fetchInstMaxNum).W)
11 | val predictBranch = Bool()
12 | val isPredictValid = Bool()
13 | }
14 |
15 | object FtqInfoBundle extends Bundle {
16 | def default = 0.U.asTypeOf(new FtqInfoBundle)
17 | }
18 |
--------------------------------------------------------------------------------
/src/src/pipeline/common/bundles/InstQueueEnqNdPort.scala:
--------------------------------------------------------------------------------
1 | package pipeline.common.bundles
2 |
3 | import chisel3._
4 | import chisel3.util.Valid
5 | import spec.Param
6 |
7 | class InstQueueEnqNdPort extends Bundle {
8 | val enqInfos = Vec(Param.fetchInstMaxNum, Valid(new FetchInstInfoBundle))
9 | }
10 |
11 | object InstQueueEnqNdPort {
12 | def default = 0.U.asTypeOf(new InstQueueEnqNdPort)
13 | }
14 |
--------------------------------------------------------------------------------
/src/src/pipeline/common/bundles/MemCsrNdPort.scala:
--------------------------------------------------------------------------------
1 | package pipeline.common.bundles
2 |
3 | import chisel3._
4 | import control.csrBundles.{CrmdBundle, DmwBundle}
5 |
6 | class MemCsrNdPort extends Bundle {
7 | val crmd = new CrmdBundle
8 | val dmw = Vec(2, new DmwBundle)
9 | }
10 |
--------------------------------------------------------------------------------
/src/src/pipeline/common/bundles/MemRequestNdPort.scala:
--------------------------------------------------------------------------------
1 | package pipeline.common.bundles
2 |
3 | import chisel3._
4 | import chisel3.experimental.BundleLiterals._
5 | import common.enums.ReadWriteSel
6 | import pipeline.common.enums.MemSizeType
7 | import spec._
8 |
9 | class MemRequestNdPort extends Bundle {
10 | val isValid = Bool()
11 | val rw = ReadWriteSel()
12 | val addr = UInt(Width.Mem.addr)
13 | val mask = UInt((Width.Mem._data / byteLength).W)
14 |
15 | val read = new Bundle {
16 | val isUnsigned = Bool()
17 | val size = MemSizeType()
18 | }
19 |
20 | val write = new Bundle {
21 | val data = UInt(Width.Mem.data)
22 | }
23 | }
24 |
25 | object MemRequestNdPort {
26 | def default = (new MemRequestNdPort).Lit(
27 | _.isValid -> false.B,
28 | _.rw -> ReadWriteSel.read,
29 | _.addr -> zeroWord,
30 | _.mask -> zeroWord,
31 | _.read.isUnsigned -> false.B,
32 | _.read.size -> MemSizeType.word,
33 | _.write.data -> zeroWord
34 | )
35 | }
36 |
--------------------------------------------------------------------------------
/src/src/pipeline/common/bundles/PcInstBundle.scala:
--------------------------------------------------------------------------------
1 | package pipeline.common.bundles
2 |
3 | import chisel3._
4 | import spec._
5 |
6 | class PcInstBundle extends Bundle {
7 | val pcAddr = UInt(Width.Reg.data)
8 | val inst = UInt(Width.Reg.data)
9 | }
10 |
--------------------------------------------------------------------------------
/src/src/pipeline/common/bundles/RobQueryPcPort.scala:
--------------------------------------------------------------------------------
1 | package pipeline.common.bundles
2 |
3 | import chisel3._
4 | import spec._
5 |
6 | class RobQueryPcPort extends Bundle {
7 | val robId = Input(UInt(Param.Width.Rob.id))
8 | val pc = Output(UInt(Width.Reg.data))
9 | }
10 |
--------------------------------------------------------------------------------
/src/src/pipeline/common/enums/AddrTransType.scala:
--------------------------------------------------------------------------------
1 | package pipeline.common.enums
2 |
3 | import chisel3.ChiselEnum
4 |
5 | object AddrTransType extends ChiselEnum {
6 | val direct, directMapping, pageTableMapping = Value
7 | }
8 |
--------------------------------------------------------------------------------
/src/src/pipeline/common/enums/CacheMaintenanceTargetType.scala:
--------------------------------------------------------------------------------
1 | package pipeline.common.enums
2 |
3 | import chisel3.ChiselEnum
4 |
5 | object CacheMaintenanceTargetType extends ChiselEnum {
6 | val inst, data = Value
7 | }
8 |
--------------------------------------------------------------------------------
/src/src/pipeline/common/enums/MemSizeType.scala:
--------------------------------------------------------------------------------
1 | package pipeline.common.enums
2 |
3 | import chisel3.ChiselEnum
4 |
5 | object MemSizeType extends ChiselEnum {
6 | val byte, halfWord, word = Value
7 | }
8 |
--------------------------------------------------------------------------------
/src/src/pipeline/common/enums/RegDataLocateSel.scala:
--------------------------------------------------------------------------------
1 | package pipeline.common.enums
2 |
3 | import chisel3.ChiselEnum
4 |
5 | object RegDataLocateSel extends ChiselEnum {
6 | val regfile, rob = Value
7 | }
8 |
--------------------------------------------------------------------------------
/src/src/pipeline/common/enums/RegDataState.scala:
--------------------------------------------------------------------------------
1 | package pipeline.common.enums
2 |
3 | import chisel3.ChiselEnum
4 |
5 | object RegDataState extends ChiselEnum {
6 | val ready, busy = Value
7 | }
8 |
--------------------------------------------------------------------------------
/src/src/pipeline/common/enums/RobDistributeSel.scala:
--------------------------------------------------------------------------------
1 | package pipeline.common.enums
2 |
3 | import chisel3.ChiselEnum
4 |
5 | object RobDistributeSel extends ChiselEnum {
6 | val robId, realData = Value
7 | }
8 |
--------------------------------------------------------------------------------
/src/src/pipeline/common/enums/RobInstState.scala:
--------------------------------------------------------------------------------
1 | package pipeline.common.enums
2 |
3 | import chisel3.ChiselEnum
4 |
5 | object RobInstState extends ChiselEnum {
6 | val empty, busy, ready = Value
7 | }
8 |
--------------------------------------------------------------------------------
/src/src/pipeline/complex/bundles/CommitFtqInfoBundle.scala:
--------------------------------------------------------------------------------
1 | package pipeline.complex.bundles
2 |
3 | import chisel3._
4 | import spec._
5 |
6 | class CommitFtqInfoBundle extends Bundle {
7 | val isBranch = Bool()
8 | val branchType = UInt(Param.BPU.BranchType.width.W)
9 | val isBranchSuccess = Bool()
10 | val isRedirect = Bool()
11 |
12 | val directionMispredict = if (Param.usePmu) Some(Bool()) else None
13 | val targetMispredict = if (Param.usePmu) Some(Bool()) else None
14 | }
15 |
16 | object CommitFtqInfoBundle {
17 | def default = 0.U.asTypeOf(new CommitFtqInfoBundle)
18 | }
19 |
--------------------------------------------------------------------------------
/src/src/pipeline/complex/bundles/InstInfoNdPort.scala:
--------------------------------------------------------------------------------
1 | package pipeline.complex.bundles
2 |
3 | import chisel3._
4 | import control.bundles._
5 | import control.enums.ExceptionPos
6 | import pipeline.common.bundles._
7 | import spec.Param.isDiffTest
8 | import spec._
9 |
10 | class InstInfoNdPort extends Bundle {
11 | val isValid = Bool()
12 | val exceptionPos = ExceptionPos()
13 | val exceptionRecord = UInt(Csr.ExceptionIndex.width)
14 | val isStore = Bool()
15 | val needRefetch = Bool()
16 | val isCsrWrite = Bool()
17 |
18 | val exeOp = UInt(Param.Width.exeOp)
19 | val robId = UInt(Param.Width.Rob.id)
20 |
21 | val load = if (isDiffTest) Some(new DifftestLoadNdPort) else None
22 | val store = if (isDiffTest) Some(new DifftestStoreNdPort) else None
23 | val tlbFill = if (isDiffTest) Some(new DifftestTlbFillNdPort) else None
24 | val timerInfo = if (isDiffTest) Some(new DifftestTimerNdPort) else None
25 | val ftqInfo = new FtqInfoBundle
26 | val ftqCommitInfo = new CommitFtqInfoBundle
27 |
28 | val isTlb = Bool()
29 |
30 | val forbidParallelCommit = Bool()
31 | }
32 |
33 | object InstInfoNdPort {
34 | def default = 0.U.asTypeOf(new InstInfoNdPort)
35 |
36 | def invalidate(instInfo: InstInfoNdPort): Unit = {
37 | instInfo.isValid := false.B
38 | instInfo.needRefetch := false.B
39 | instInfo.exceptionPos := ExceptionPos.none
40 | instInfo.exeOp := ExeInst.Op.nop
41 | instInfo.isCsrWrite := false.B
42 | instInfo.isTlb := false.B
43 | instInfo.isStore := false.B
44 | instInfo.forbidParallelCommit := false.B
45 |
46 | if (isDiffTest) {
47 | instInfo.load.get.en := false.B
48 | instInfo.store.get.en := false.B
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/src/pipeline/complex/bundles/RobInstStoreBundle.scala:
--------------------------------------------------------------------------------
1 | package pipeline.complex.bundles
2 |
3 | import chisel3._
4 | import pipeline.common.bundles.PcInstBundle
5 | import pipeline.common.enums.RobInstState
6 | import pipeline.complex.commit.WbNdPort
7 |
8 | class RobInstStoreBundle extends Bundle {
9 | val state = RobInstState()
10 | val wbPort = new WbNdPort
11 | val fetchInfo = new PcInstBundle
12 | }
13 |
14 | object RobInstStoreBundle {
15 | def default = 0.U.asTypeOf(new RobInstStoreBundle)
16 | }
17 |
--------------------------------------------------------------------------------
/src/src/pipeline/complex/dataforward/DataForwardStage.scala:
--------------------------------------------------------------------------------
1 | package pipeline.complex.dataforward
2 |
3 | import chisel3._
4 | import common.bundles.RfWriteNdPort
5 | import pipeline.complex.dataforward.bundles.ReadPortWithValid
6 | import spec._
7 | class DataForwardStage(
8 | dataForwardNum: Int = Param.dataForwardInputNum,
9 | readNum: Int = Param.regFileReadNum)
10 | extends Module {
11 | val io = IO(new Bundle {
12 | val writePorts = Input(Vec(dataForwardNum, new RfWriteNdPort))
13 | val readPorts = Vec(readNum, new ReadPortWithValid)
14 | })
15 |
16 | io.readPorts.foreach { readPort =>
17 | readPort.valid := false.B
18 | readPort.data := zeroWord
19 | when(readPort.en) {
20 | io.writePorts.reverse.foreach { writePort =>
21 | when(writePort.en && (readPort.addr === writePort.addr)) {
22 | readPort.data := writePort.data
23 | readPort.valid := true.B
24 | }
25 | }
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/src/pipeline/complex/dataforward/bundles/ReadPortWithValid.scala:
--------------------------------------------------------------------------------
1 | package pipeline.complex.dataforward.bundles
2 |
3 | import chisel3._
4 | import spec._
5 |
6 | class ReadPortWithValid extends Bundle {
7 | val en = Input(Bool())
8 | val addr = Input(UInt(Width.Reg.addr))
9 | val valid = Output(Bool())
10 | val data = Output(UInt(Width.Reg.data))
11 | }
12 |
--------------------------------------------------------------------------------
/src/src/pipeline/complex/dispatch/bundles/IssueInfoWithValidBundle.scala:
--------------------------------------------------------------------------------
1 | package pipeline.complex.dispatch.bundles
2 |
3 | import chisel3._
4 | import chisel3.experimental.BundleLiterals._
5 | import pipeline.complex.dispatch.RegReadNdPort
6 |
7 | class RegReadPortWithValidBundle extends Bundle {
8 | val valid = Bool()
9 | val issueInfo = new RegReadNdPort
10 | }
11 |
12 | object RegReadPortWithValidBundle {
13 | def default = (new RegReadPortWithValidBundle).Lit(
14 | _.valid -> false.B,
15 | _.issueInfo -> RegReadNdPort.default
16 | )
17 | }
18 |
--------------------------------------------------------------------------------
/src/src/pipeline/complex/dispatch/bundles/PreExeInstNdPort.scala:
--------------------------------------------------------------------------------
1 | package pipeline.complex.dispatch.bundles
2 |
3 | import chisel3._
4 | import common.bundles.RfAccessInfoNdPort
5 | import spec._
6 |
7 | class PreExeInstNdPort(readNum: Int = Param.instRegReadNum) extends Bundle {
8 | // Micro-instruction for execution stage
9 | val exeSel = UInt(Param.Width.exeSel)
10 | val exeOp = UInt(Param.Width.exeOp)
11 |
12 | // GPR read (`readNum`)
13 | val gprReadPorts = Vec(readNum, new RfAccessInfoNdPort)
14 | val csrReadEn = Bool()
15 | val csrWriteEn = Bool()
16 |
17 | // GPR write
18 | val gprWritePort = new RfAccessInfoNdPort
19 |
20 | // Immediate
21 | val isHasImm = Bool()
22 | val imm = UInt(Width.Reg.data)
23 |
24 | // Branch jump addr
25 | val jumpBranchAddr = UInt(Width.Reg.data)
26 |
27 | def loadStoreImm = jumpBranchAddr
28 |
29 | def csrAddr = jumpBranchAddr
30 |
31 | def code = jumpBranchAddr
32 |
33 | def tlbInvalidateInst = jumpBranchAddr
34 |
35 | val needRefetch = Bool()
36 | val isTlb = Bool()
37 |
38 | val issueEn = Vec(Param.pipelineNum, Bool())
39 | val forbidOutOfOrder = Bool()
40 | val isPrivilege = Bool()
41 | val isBranch = Bool()
42 | val branchType = UInt(Param.BPU.BranchType.width.W)
43 | // TODO: Signals in this port is not sufficient
44 | }
45 |
46 | object PreExeInstNdPort {
47 | def default = 0.U.asTypeOf(new PreExeInstNdPort)
48 | }
49 |
--------------------------------------------------------------------------------
/src/src/pipeline/complex/dispatch/bundles/RenameRequestNdPort.scala:
--------------------------------------------------------------------------------
1 | package pipeline.complex.dispatch.bundles
2 |
3 | import chisel3._
4 | import common.bundles.RfAccessInfoNdPort
5 |
6 | class RenameRequestNdPort(
7 | regReadNum: Int = 2,
8 | arfAddrWidth: internal.firrtl.Width = 5.W)
9 | extends Bundle {
10 | val arfWritePort = new RfAccessInfoNdPort(arfAddrWidth)
11 | val arfReadPorts = Vec(regReadNum, new RfAccessInfoNdPort(arfAddrWidth))
12 | }
13 |
--------------------------------------------------------------------------------
/src/src/pipeline/complex/dispatch/bundles/RenameResultNdPort.scala:
--------------------------------------------------------------------------------
1 | package pipeline.complex.dispatch.bundles
2 |
3 | import chisel3._
4 | import common.bundles.RfAccessInfoNdPort
5 |
6 | class RenameResultNdPort(
7 | regReadNum: Int = 2,
8 | grfAddrWidth: internal.firrtl.Width = 6.W)
9 | extends Bundle {
10 | val grfWritePort = new RfAccessInfoNdPort(grfAddrWidth)
11 | val grfReadPorts = Vec(regReadNum, new RfAccessInfoNdPort(grfAddrWidth))
12 | }
13 |
14 | object RenameResultNdPort {
15 | def setDefault(port: RenameResultNdPort) = {
16 | port.grfWritePort := RfAccessInfoNdPort.default
17 | port.grfReadPorts.foreach(_ := RfAccessInfoNdPort.default)
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/src/pipeline/complex/dispatch/bundles/ReservationStationBundle.scala:
--------------------------------------------------------------------------------
1 | package pipeline.complex.dispatch.bundles
2 |
3 | import chisel3._
4 | import pipeline.complex.dispatch.RegReadNdPort
5 | import pipeline.complex.rob.bundles.RobReadResultNdPort
6 |
7 | class ReservationStationBundle extends Bundle {
8 | val regReadPort = new RegReadNdPort
9 | val robResult = new RobReadResultNdPort
10 | }
11 |
12 | object ReservationStationBundle {
13 | def default = 0.U.asTypeOf(new ReservationStationBundle)
14 | }
15 |
--------------------------------------------------------------------------------
/src/src/pipeline/complex/dispatch/bundles/ScoreboardChangeNdPort.scala:
--------------------------------------------------------------------------------
1 | package pipeline.complex.dispatch.bundles
2 |
3 | import chisel3._
4 | import chisel3.experimental.BundleLiterals._
5 | import spec._
6 |
7 | class ScoreboardChangeNdPort(addrWidth: internal.firrtl.Width = Width.Reg.addr) extends Bundle {
8 | val en = Bool()
9 | }
10 |
11 | object ScoreboardChangeNdPort {
12 | def default = (new ScoreboardChangeNdPort).Lit(
13 | _.en -> false.B
14 | )
15 | }
16 |
--------------------------------------------------------------------------------
/src/src/pipeline/complex/dispatch/enums/IssueStageState.scala:
--------------------------------------------------------------------------------
1 | package pipeline.complex.dispatch.enums
2 |
3 | import chisel3.ChiselEnum
4 |
5 | object IssueStageState extends ChiselEnum {
6 | val nonBlocking, blocking = Value
7 | }
8 |
--------------------------------------------------------------------------------
/src/src/pipeline/complex/dispatch/enums/PrfState.scala:
--------------------------------------------------------------------------------
1 | package pipeline.complex.dispatch.enums
2 |
3 | import chisel3.ChiselEnum
4 |
5 | object PrfState extends ChiselEnum {
6 | val free, busy, retire = Value
7 | }
8 |
--------------------------------------------------------------------------------
/src/src/pipeline/complex/dispatch/enums/ScoreboardState.scala:
--------------------------------------------------------------------------------
1 | package pipeline.complex.dispatch.enums
2 |
3 | import chisel3.ChiselEnum
4 |
5 | object ScoreboardState extends ChiselEnum {
6 | val free, beforeExe, afterExe = Value
7 | }
8 |
--------------------------------------------------------------------------------
/src/src/pipeline/complex/dispatch/rs/BaseReservationStation.scala:
--------------------------------------------------------------------------------
1 | package pipeline.complex.dispatch.rs
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import pipeline.complex.dispatch.bundles.ReservationStationBundle
6 | import pipeline.complex.pmu.bundles.PmuDispatchBundle
7 | import pipeline.complex.rob.bundles.InstWbNdPort
8 | import spec.Param
9 |
10 | abstract class BaseReservationStation(
11 | queueLength: Int,
12 | enqMaxNum: Int,
13 | deqMaxNum: Int,
14 | channelNum: Int,
15 | channelLength: Int)
16 | extends Module {
17 | val io = IO(new Bundle {
18 | val isFlush = Input(Bool())
19 | val enqueuePorts = Vec(enqMaxNum, Flipped(Decoupled(new ReservationStationBundle)))
20 | val dequeuePorts = Vec(deqMaxNum, Decoupled(new ReservationStationBundle))
21 | val writebacks = Input(Vec(Param.pipelineNum, new InstWbNdPort))
22 |
23 | val pmu_dispatchInfo = if (Param.usePmu) Some(Output(new PmuDispatchBundle)) else None
24 | })
25 | require(queueLength == channelNum * channelLength)
26 | }
27 |
--------------------------------------------------------------------------------
/src/src/pipeline/complex/execution/bundles/JumpBranchInfoNdPort.scala:
--------------------------------------------------------------------------------
1 | package pipeline.complex.execution.bundles
2 |
3 | import chisel3._
4 | import chisel3.experimental.BundleLiterals._
5 | import spec._
6 |
7 | class JumpBranchInfoNdPort extends Bundle {
8 | val en = Bool()
9 | val pcAddr = UInt(Width.Reg.data)
10 | }
11 |
12 | object JumpBranchInfoNdPort {
13 | def default = (new JumpBranchInfoNdPort).Lit(
14 | _.en -> false.B,
15 | _.pcAddr -> zeroWord
16 | )
17 | }
18 |
--------------------------------------------------------------------------------
/src/src/pipeline/complex/memory/bundles/StoreInfoBundle.scala:
--------------------------------------------------------------------------------
1 | package pipeline.complex.memory.bundles
2 |
3 | import chisel3._
4 | import spec._
5 |
6 | class StoreInfoBundle extends Bundle {
7 | val addr = UInt(Width.Mem.addr)
8 | val mask = UInt((Width.Mem._data / byteLength).W)
9 | val data = UInt(Width.Mem.data)
10 | val isCached = Bool()
11 | }
12 |
--------------------------------------------------------------------------------
/src/src/pipeline/complex/pmu/bundles/PmuBranchMisPredictExeNdPort.scala:
--------------------------------------------------------------------------------
1 | package pipeline.complex.pmu.bundles
2 |
3 | import chisel3._
4 |
5 | class PmuBranchMisPredictExeNdPort extends Bundle {
6 | val directionMispredict = Bool()
7 | val targetMispredict = Bool()
8 | }
9 |
--------------------------------------------------------------------------------
/src/src/pipeline/complex/pmu/bundles/PmuBranchPredictNdPort.scala:
--------------------------------------------------------------------------------
1 | package pipeline.complex.pmu.bundles
2 |
3 | import chisel3._
4 | import spec._
5 |
6 | class PmuBranchPredictNdPort extends Bundle {
7 | val isBranch = Bool()
8 | val isRedirect = Bool()
9 | val branchType = UInt(Param.BPU.BranchType.width.W)
10 | val directionMispredict = Bool()
11 | val targetMispredict = Bool()
12 | }
13 |
--------------------------------------------------------------------------------
/src/src/pipeline/complex/pmu/bundles/PmuCacheNdPort.scala:
--------------------------------------------------------------------------------
1 | package pipeline.complex.pmu.bundles
2 |
3 | import chisel3._
4 |
5 | class PmuCacheNdPort extends Bundle {
6 | val newReq = Bool()
7 | val cacheHit = Bool()
8 | val cacheMiss = Bool()
9 | val lineReplace = Bool()
10 | }
11 |
--------------------------------------------------------------------------------
/src/src/pipeline/complex/pmu/bundles/PmuDispatchBundle.scala:
--------------------------------------------------------------------------------
1 | package pipeline.complex.pmu.bundles
2 |
3 | import chisel3._
4 |
5 | class PmuDispatchBundle extends Bundle {
6 | val bubbleFromBackend = Bool()
7 | val bubbleFromDataDependence = Bool()
8 | val bubbleFromRSEmpty = Bool()
9 | val isFull = Bool()
10 | val enqueue = Bool()
11 | }
12 |
--------------------------------------------------------------------------------
/src/src/pipeline/complex/pmu/bundles/PmuNdPort.scala:
--------------------------------------------------------------------------------
1 | package pipeline.complex.pmu.bundles
2 |
3 | import chisel3._
4 |
5 | class PmuNdPort extends Bundle {
6 | val instqueueFull = Input(Bool())
7 | val instqueueFullValid = Input(Bool())
8 | val branchInfo = Input(new PmuBranchPredictNdPort)
9 | }
10 |
--------------------------------------------------------------------------------
/src/src/pipeline/complex/pmu/bundles/PmuStoreQueueNdPort.scala:
--------------------------------------------------------------------------------
1 | package pipeline.complex.pmu.bundles
2 |
3 | import chisel3._
4 |
5 | class PmuStoreQueueNdPort extends Bundle {
6 | val storeOutValid = Bool()
7 | val storeFull = Bool()
8 | }
9 |
--------------------------------------------------------------------------------
/src/src/pipeline/complex/queue/bundles/DecodeOutNdPort.scala:
--------------------------------------------------------------------------------
1 | package pipeline.complex.queue.bundles
2 |
3 | import chisel3._
4 | import pipeline.complex.dispatch.bundles.PreExeInstNdPort
5 |
6 | class DecodeOutNdPort extends Bundle {
7 | // Is instruction matched
8 | val isMatched = Bool()
9 |
10 | val info = new PreExeInstNdPort
11 | }
12 |
13 | object DecodeOutNdPort {
14 | def default = 0.U.asTypeOf(new DecodeOutNdPort)
15 | }
16 |
--------------------------------------------------------------------------------
/src/src/pipeline/complex/queue/bundles/DecodePort.scala:
--------------------------------------------------------------------------------
1 | package pipeline.complex.queue.bundles
2 |
3 | import chisel3._
4 | import pipeline.common.bundles.FetchInstInfoBundle
5 |
6 | class DecodePort extends Bundle {
7 | // The original instruction
8 | val instInfoPort = Input(new FetchInstInfoBundle)
9 |
10 | // Output info
11 | val out = Output(new DecodeOutNdPort)
12 | }
13 |
--------------------------------------------------------------------------------
/src/src/pipeline/complex/queue/decode/Decoder.scala:
--------------------------------------------------------------------------------
1 | package pipeline.complex.queue.decode
2 |
3 | import chisel3._
4 | import pipeline.complex.queue.bundles.DecodePort
5 | import spec._
6 |
7 | object DispatchType extends Enumeration {
8 | type Type = Value
9 | val common, loadStore, csrOrBranch = Value
10 | }
11 |
12 | abstract class Decoder extends Module {
13 | // A decoder should:
14 | // 1) Extract and extend immediate from instruction, if it has
15 | // 2) Extract register information from instruction
16 | // 3) Something else...
17 |
18 | val io = IO(new DecodePort)
19 |
20 | io.out.info.issueEn.zipWithIndex.foreach {
21 | case (en, idx) =>
22 | en := false.B
23 | }
24 |
25 | def selectIssueEn(dispatchType: DispatchType.Type): Unit = {
26 | dispatchType match {
27 | case DispatchType.common => {
28 | io.out.info.issueEn.zipWithIndex.foreach {
29 | case (en, idx) =>
30 | en := (idx != Param.loadStoreIssuePipelineIndex).B
31 | }
32 | }
33 | case DispatchType.csrOrBranch => {
34 | io.out.info.issueEn.zipWithIndex.foreach {
35 | case (en, idx) =>
36 | en := (idx == Param.csrIssuePipelineIndex).B
37 | }
38 | }
39 | case DispatchType.loadStore => {
40 | {
41 | io.out.info.issueEn.zipWithIndex.foreach {
42 | case (en, idx) =>
43 | en := (idx == Param.loadStoreIssuePipelineIndex).B
44 | }
45 | }
46 | }
47 | case _ => throw new Exception("dispatchType error")
48 | }
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/src/src/pipeline/complex/queue/decode/Decoder_2R.scala:
--------------------------------------------------------------------------------
1 | package pipeline.complex.queue.decode
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import pipeline.complex.queue.bundles.DecodeOutNdPort
6 | import spec.Inst.{_2R => Inst}
7 | import spec._
8 |
9 | class Decoder_2R extends Decoder {
10 | io.out := DecodeOutNdPort.default
11 |
12 | val opcode = WireDefault(io.instInfoPort.inst(31, 10))
13 | val rj = WireDefault(io.instInfoPort.inst(9, 5))
14 | val rd = WireDefault(io.instInfoPort.inst(4, 0))
15 | val rdIsNotZero = WireDefault(rd.orR)
16 |
17 | io.out.info.isHasImm := false.B
18 |
19 | switch(opcode) {
20 | is(Inst.rdcnt_id_vl) {
21 | selectIssueEn(DispatchType.csrOrBranch)
22 | io.out.info.forbidOutOfOrder := true.B
23 |
24 | io.out.isMatched := true.B
25 | when(rj.orR) {
26 | io.out.info.csrReadEn := true.B
27 | io.out.info.csrAddr := Csr.Index.tid
28 | io.out.info.exeOp := ExeInst.Op.csrrd
29 | io.out.info.gprWritePort.en := true.B
30 | io.out.info.gprWritePort.addr := rj
31 | }.otherwise {
32 | io.out.info.gprWritePort.addr := rd
33 | io.out.info.gprWritePort.en := rdIsNotZero
34 | io.out.info.exeOp := ExeInst.Op.rdcntvl_w
35 | }
36 | }
37 | is(Inst.rdcnt_vh) {
38 | selectIssueEn(DispatchType.csrOrBranch)
39 | io.out.info.forbidOutOfOrder := true.B
40 |
41 | io.out.isMatched := true.B
42 | io.out.info.gprWritePort.en := rdIsNotZero
43 | io.out.info.gprWritePort.addr := rd
44 | io.out.info.exeOp := ExeInst.Op.rdcntvh_w
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/src/pipeline/complex/queue/decode/Decoder_4R.scala:
--------------------------------------------------------------------------------
1 | package pipeline.complex.queue.decode
2 |
3 | import chisel3._
4 | import pipeline.complex.queue.bundles.DecodeOutNdPort
5 |
6 | class Decoder_4R extends Decoder {
7 |
8 | io.out := DecodeOutNdPort.default
9 |
10 | // TODO: This is empty
11 |
12 | val opcode = WireDefault(io.instInfoPort.inst(31, 20))
13 | val ra = WireDefault(io.instInfoPort.inst(19, 15))
14 | val rk = WireDefault(io.instInfoPort.inst(14, 10))
15 | val rj = WireDefault(io.instInfoPort.inst(9, 5))
16 | val rd = WireDefault(io.instInfoPort.inst(4, 0))
17 |
18 | io.out.info.isHasImm := false.B
19 | }
20 |
--------------------------------------------------------------------------------
/src/src/pipeline/complex/rob/bundles/InstWbNdPort.scala:
--------------------------------------------------------------------------------
1 | package pipeline.complex.rob.bundles
2 |
3 | import chisel3._
4 | import spec._
5 |
6 | class InstWbNdPort extends Bundle {
7 | val en = Bool()
8 | val robId = UInt(Param.Width.Rob.id)
9 | val data = UInt(Width.Reg.data)
10 | }
11 |
12 | object InstWbNdPort {
13 | def default = 0.U.asTypeOf(new InstWbNdPort)
14 | }
15 |
--------------------------------------------------------------------------------
/src/src/pipeline/complex/rob/bundles/RobDistributeBundle.scala:
--------------------------------------------------------------------------------
1 | package pipeline.complex.rob.bundles
2 |
3 | import chisel3._
4 | import chisel3.experimental.BundleLiterals._
5 | import pipeline.common.enums.RobDistributeSel
6 | import spec._
7 |
8 | class RobDistributeBundle extends Bundle {
9 | val sel = RobDistributeSel()
10 | val result = UInt(Width.Reg.data)
11 | }
12 |
13 | object RobDistributeBundle {
14 | def default = (new RobDistributeBundle).Lit(
15 | _.sel -> RobDistributeSel.realData,
16 | _.result -> 0.U
17 | )
18 | }
19 |
--------------------------------------------------------------------------------
/src/src/pipeline/complex/rob/bundles/RobIdDistributePort.scala:
--------------------------------------------------------------------------------
1 | package pipeline.complex.rob.bundles
2 |
3 | import chisel3._
4 |
5 | class RobIdDistributePort(idLength: Int = 32) extends Bundle {
6 | val writeEn = Input(Bool())
7 | val id = Output(UInt(idLength.W))
8 | }
9 |
--------------------------------------------------------------------------------
/src/src/pipeline/complex/rob/bundles/RobMatchBundle.scala:
--------------------------------------------------------------------------------
1 | package pipeline.complex.rob.bundles
2 |
3 | import chisel3._
4 | import pipeline.common.enums.RegDataState
5 | import spec._
6 |
7 | class RobMatchBundle extends Bundle {
8 | val state = RegDataState()
9 | // val robId = UInt(Param.Width.Rob.id)
10 | val data = UInt(Width.Reg.data)
11 | }
12 |
13 | object RobMatchBundle {
14 | def default = 0.U.asTypeOf(new RobMatchBundle)
15 | }
16 |
--------------------------------------------------------------------------------
/src/src/pipeline/complex/rob/bundles/RobReadRequestNdPort.scala:
--------------------------------------------------------------------------------
1 | package pipeline.complex.rob.bundles
2 |
3 | import chisel3._
4 | import common.bundles.RfAccessInfoNdPort
5 | import pipeline.common.bundles.PcInstBundle
6 | import spec._
7 |
8 | class RobReadRequestNdPort extends Bundle {
9 | val writeRequest = new RfAccessInfoNdPort
10 | val readRequests = Vec(Param.regFileReadNum, new RfAccessInfoNdPort)
11 | val fetchInfo = new PcInstBundle
12 | }
13 |
14 | object RobReadRequestNdPort {
15 | def default = 0.U.asTypeOf(new RobReadRequestNdPort)
16 | }
17 |
--------------------------------------------------------------------------------
/src/src/pipeline/complex/rob/bundles/RobReadResultNdPort.scala:
--------------------------------------------------------------------------------
1 | package pipeline.complex.rob.bundles
2 |
3 | import chisel3._
4 | import chisel3.experimental.BundleLiterals._
5 | import chisel3.experimental.VecLiterals._
6 | import spec._
7 |
8 | class RobReadResultNdPort extends Bundle {
9 | val robId = UInt(Param.Width.Rob.id)
10 | val readResults = Vec(Param.regFileReadNum, new RobDistributeBundle)
11 | }
12 |
13 | object RobReadResultNdPort {
14 | def default = (new RobReadResultNdPort).Lit(
15 | _.robId -> 0.U,
16 | _.readResults -> Vec.Lit(Seq.fill(Param.regFileReadNum)(RobDistributeBundle.default): _*)
17 | )
18 | }
19 |
--------------------------------------------------------------------------------
/src/src/pipeline/complex/rob/lvt/LiveValueTable.scala:
--------------------------------------------------------------------------------
1 | package pipeline.complex.rob.lvt
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import pipeline.complex.rob.lvt.bundles._
6 |
7 | class LiveValueTable[T <: Data](
8 | elemFactory: => T,
9 | blankElem: => T,
10 | elemNum: Int,
11 | readNum: Int,
12 | writeNum: Int,
13 | hasFlush: Boolean = false)
14 | extends Module {
15 | val addrWidth = log2Ceil(elemNum)
16 |
17 | val io = IO(new Bundle {
18 | val readPorts = Vec(readNum, new LvtReadPort(addrWidth, elemFactory))
19 | val writePorts = Vec(writeNum, Input(new LvtWriteNdPort(addrWidth, elemFactory)))
20 | val flushPort = if (hasFlush) Some(Input(Valid(Vec(elemNum, elemFactory)))) else None
21 | })
22 |
23 | val lastValidTable = Module(new LvtLastValidTable(elemNum, readNum, writeNum, hasFlush = hasFlush))
24 | lastValidTable.io.readPorts.zip(io.readPorts).foreach {
25 | case (dst, src) =>
26 | dst.addr := src.addr
27 | }
28 | lastValidTable.io.writePorts.zip(io.writePorts).foreach {
29 | case (dst, src) =>
30 | dst.en := src.en
31 | dst.addr := src.addr
32 | dst.data := DontCare
33 | }
34 | if (hasFlush) {
35 | lastValidTable.io.isFlush.get := io.flushPort.get.valid
36 | }
37 |
38 | val readDataBuffer = Wire(Vec(writeNum, Vec(readNum, elemFactory)))
39 |
40 | for (writeIdx <- 0 until writeNum) {
41 | for (readIdx <- 0 until readNum) {
42 | val lutHasFlush = writeIdx == 0 && hasFlush
43 | val lutRam = Module(new LutRam(elemFactory, blankElem, elemNum, hasFlush = lutHasFlush))
44 | lutRam.io.writePort := io.writePorts(writeIdx)
45 | lutRam.io.readPort.addr := io.readPorts(readIdx).addr
46 | readDataBuffer(writeIdx)(readIdx) := lutRam.io.readPort.data
47 | if (lutHasFlush) {
48 | lutRam.io.flushPort.get.valid := io.flushPort.get.valid
49 | lutRam.io.flushPort.get.bits.zip(io.flushPort.get.bits).foreach {
50 | case (dst, src) =>
51 | dst := src
52 | }
53 | }
54 | }
55 | }
56 |
57 | io.readPorts.zipWithIndex.foreach {
58 | case (r, idx) =>
59 | r.data := readDataBuffer(lastValidTable.io.readPorts(idx).data)(idx)
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/src/pipeline/complex/rob/lvt/LutRam.scala:
--------------------------------------------------------------------------------
1 | package pipeline.complex.rob.lvt
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import pipeline.complex.rob.lvt.bundles.{LvtReadPort, LvtWriteNdPort}
6 |
7 | class LutRam[T <: Data](
8 | elemFactory: => T,
9 | blankElem: => T,
10 | elemNum: Int,
11 | hasFlush: Boolean = false)
12 | extends Module {
13 |
14 | val addrWidth = log2Ceil(elemNum)
15 |
16 | val io = IO(new Bundle {
17 | val readPort = new LvtReadPort(addrWidth, elemFactory)
18 | val writePort = Input(new LvtWriteNdPort(addrWidth, elemFactory))
19 | val flushPort = if (hasFlush) Some(Input(Valid(Vec(elemNum, elemFactory)))) else None
20 | })
21 | // val ram = RegInit(VecInit(Seq.fill(elemNum)(blankElem)))
22 | val ram = Reg(Vec(elemNum, elemFactory))
23 | ram.foreach { reg =>
24 | reg := reg
25 | }
26 |
27 | io.readPort.data := ram(io.readPort.addr)
28 |
29 | when(io.writePort.en) {
30 | ram(io.writePort.addr) := io.writePort.data
31 | }
32 |
33 | if (hasFlush) {
34 | when(io.flushPort.get.valid) {
35 | ram.zip(io.flushPort.get.bits).foreach {
36 | case (dst, src) =>
37 | dst := src
38 | }
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/src/pipeline/complex/rob/lvt/LvtLastValidTable.scala:
--------------------------------------------------------------------------------
1 | package pipeline.complex.rob.lvt
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import pipeline.complex.rob.lvt.bundles.{LvtReadPort, LvtWriteNdPort}
6 |
7 | class LvtLastValidTable(
8 | elemNum: Int,
9 | readNum: Int,
10 | writeNum: Int,
11 | hasFlush: Boolean = false)
12 | extends Module {
13 | val writeIdWidth = log2Ceil(writeNum)
14 | val addrWidth = log2Ceil(elemNum)
15 |
16 | val io = IO(new Bundle {
17 | val readPorts = Vec(
18 | readNum,
19 | new LvtReadPort(addrWidth, UInt(writeIdWidth.W))
20 | )
21 | val writePorts = Vec(
22 | writeNum,
23 | Input(new LvtWriteNdPort(addrWidth, UInt(0.W)))
24 | )
25 | val isFlush = if (hasFlush) Some(Input(Bool())) else None
26 | })
27 |
28 | val lastValidRegs = RegInit(VecInit(Seq.fill(elemNum)(0.U(writeIdWidth.W))))
29 | io.writePorts.zipWithIndex.foreach {
30 | case (w, idx) =>
31 | when(w.en) {
32 | lastValidRegs(w.addr) := idx.U
33 | }
34 | }
35 |
36 | io.readPorts.foreach { r =>
37 | r.data := lastValidRegs(r.addr)
38 | }
39 |
40 | if (hasFlush) {
41 | when(io.isFlush.get) {
42 | lastValidRegs.foreach(_ := 0.U)
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/src/pipeline/complex/rob/lvt/bundles/LvtReadPort.scala:
--------------------------------------------------------------------------------
1 | package pipeline.complex.rob.lvt.bundles
2 |
3 | import chisel3._
4 |
5 | class LvtReadPort[T <: Data](
6 | addrWidth: Int,
7 | elemFactory: => T)
8 | extends Bundle {
9 | val addr = Input(UInt(addrWidth.W))
10 | val data = Output(elemFactory)
11 | }
12 |
--------------------------------------------------------------------------------
/src/src/pipeline/complex/rob/lvt/bundles/LvtWriteNdPort.scala:
--------------------------------------------------------------------------------
1 | package pipeline.complex.rob.lvt.bundles
2 |
3 | import chisel3._
4 |
5 | class LvtWriteNdPort[T <: Data](
6 | addrWidth: Int,
7 | elemFactory: => T)
8 | extends Bundle {
9 | val en = Bool()
10 | val addr = UInt(addrWidth.W)
11 | val data = elemFactory
12 | }
13 |
--------------------------------------------------------------------------------
/src/src/pipeline/simple/RegMatchTable.scala:
--------------------------------------------------------------------------------
1 | package pipeline.simple
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import pipeline.common.enums.RegDataState
6 | import pipeline.simple.bundles.{RegMatchBundle, RegOccupyNdPort, RegReadPort, RegWakeUpNdPort}
7 | import spec._
8 | import utils.MultiMux1
9 |
10 | class RegMatchTable(
11 | issueNum: Int = Param.issueInstInfoMaxNum,
12 | pipelineNum: Int = Param.pipelineNum)
13 | extends Module {
14 |
15 | val io = IO(new Bundle {
16 |
17 | val occupyPorts = Input(Vec(issueNum, new RegOccupyNdPort))
18 | val regReadPorts = Vec(issueNum, Vec(Param.regFileReadNum, new RegReadPort))
19 |
20 | val wakeUpPorts = Input(Vec(pipelineNum + 1, new RegWakeUpNdPort))
21 |
22 | val regfileDatas = Input(Vec(Count.reg, UInt(Width.Reg.data)))
23 |
24 | val isFlush = Input(Bool())
25 | })
26 |
27 | // common match table
28 | val matchTable = RegInit(VecInit(Seq.fill(spec.Count.reg)(RegMatchBundle.default)))
29 | val wbNextMatchTableData = Wire(Vec(Count.reg, Valid(UInt(Width.Reg.data))))
30 | matchTable.zip(wbNextMatchTableData).foreach {
31 | case (dst, src) =>
32 | src.valid := dst.state === RegDataState.ready
33 | src.bits := dst.data
34 | dst.state := Mux(src.valid, RegDataState.ready, RegDataState.busy)
35 | dst.data := src.bits
36 | dst.robId := dst.robId
37 | }
38 |
39 | io.regReadPorts.foreach { readPorts =>
40 | readPorts.foreach { r =>
41 | r.data.valid := wbNextMatchTableData(r.addr).valid
42 | r.data.bits := Mux(r.data.valid, wbNextMatchTableData(r.addr).bits, matchTable(r.addr).robId)
43 | }
44 | }
45 |
46 | // update match table
47 | matchTable.zip(wbNextMatchTableData).foreach {
48 | case (elem, nextElem) =>
49 | val mux = Module(new MultiMux1(pipelineNum + 1, UInt(spec.Width.Reg.data), zeroWord))
50 | mux.io.inputs.zip(io.wakeUpPorts).foreach {
51 | case (input, wakeUpPort) =>
52 | input.valid := wakeUpPort.en &&
53 | wakeUpPort.robId === elem.robId
54 | input.bits := wakeUpPort.data
55 | }
56 | when(mux.io.output.valid && elem.state === RegDataState.busy) {
57 | nextElem.valid := true.B
58 | nextElem.bits := mux.io.output.bits
59 | }
60 | }
61 |
62 | // occupy port for dispatch
63 | io.occupyPorts.foreach { occupy =>
64 | when(occupy.en) {
65 | matchTable(occupy.addr).state := RegDataState.busy
66 | matchTable(occupy.addr).robId := occupy.robId
67 | }
68 | }
69 |
70 | when(io.isFlush) {
71 | // Reset registers
72 | matchTable.zip(io.regfileDatas).foreach {
73 | case (dst, src) => {
74 | dst.state := RegDataState.ready
75 | dst.data := src
76 | }
77 | }
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/src/pipeline/simple/SimpleExeStage.scala:
--------------------------------------------------------------------------------
1 | package pipeline.simple
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import common.BaseStage
6 | import pipeline.simple.bundles.{RegWakeUpNdPort, WbNdPort}
7 | import pipeline.simple.execution.Alu
8 | import spec.ExeInst.OpBundle
9 |
10 | class SimpleExeStage
11 | extends BaseStage(
12 | new ExeNdPort,
13 | new WbNdPort,
14 | ExeNdPort.default,
15 | Some(new RegWakeUpNdPort)
16 | ) {
17 | val out = Wire(new WbNdPort)
18 | val outValid = Wire(Bool())
19 | resultOutReg.bits := out
20 | resultOutReg.valid := outValid
21 |
22 | val peer = io.peer.get
23 | peer.en := outValid && selectedIn.gprWritePort.en
24 | peer.addr := selectedIn.gprWritePort.addr
25 | peer.data := out.gprWrite.data
26 | peer.robId := selectedIn.instInfo.robId
27 |
28 | // ALU module
29 | val alu = Module(new Alu)
30 |
31 | isComputed := alu.io.outputValid
32 | out := DontCare
33 | out.instInfo := selectedIn.instInfo
34 | out.gprWrite.en := selectedIn.gprWritePort.en
35 | out.gprWrite.addr := selectedIn.gprWritePort.addr
36 | outValid := isComputed && selectedIn.instInfo.isValid
37 |
38 | // alu
39 |
40 | // ALU input
41 | alu.io.isFlush := io.isFlush
42 | alu.io.inputValid := selectedIn.instInfo.isValid
43 | alu.io.aluInst.op := selectedIn.instInfo.exeOp
44 | alu.io.aluInst.leftOperand := selectedIn.leftOperand
45 | alu.io.aluInst.rightOperand := selectedIn.rightOperand
46 | alu.io.aluInst.jumpBranchAddr := DontCare
47 |
48 | out.gprWrite.data := DontCare
49 |
50 | switch(selectedIn.instInfo.exeOp.sel) {
51 | is(OpBundle.sel_arthOrLogic) {
52 | out.gprWrite.data := alu.io.result.logic
53 | }
54 | is(OpBundle.sel_mulDiv) {
55 | out.gprWrite.data := alu.io.result.mulDiv
56 | }
57 | is(OpBundle.sel_readTimeOrShift) {
58 | out.gprWrite.data := alu.io.result.shift
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/src/pipeline/simple/bundles/CommitFtqInfoBundle.scala:
--------------------------------------------------------------------------------
1 | package pipeline.simple.bundles
2 |
3 | import chisel3._
4 | import spec._
5 |
6 | class CommitFtqInfoBundle extends Bundle {
7 | val isRedirect = Bool()
8 |
9 | val isBranch = Option.when(Param.usePmu)(Bool())
10 | val branchType = Option.when(Param.usePmu)(UInt(Param.BPU.BranchType.width.W))
11 | val directionMispredict = if (Param.usePmu) Some(Bool()) else None
12 | val targetMispredict = if (Param.usePmu) Some(Bool()) else None
13 | }
14 |
15 | object CommitFtqInfoBundle {
16 | def default = 0.U.asTypeOf(new CommitFtqInfoBundle)
17 | }
18 |
--------------------------------------------------------------------------------
/src/src/pipeline/simple/bundles/FtqPredictInfoBundle.scala:
--------------------------------------------------------------------------------
1 | package pipeline.simple.bundles
2 |
3 | import chisel3._
4 | import spec._
5 | import chisel3.util._
6 |
7 | class FtqPredictInfoBundle extends Bundle {
8 |
9 | val idxInBlock = UInt(log2Ceil(Param.fetchInstMaxNum).W)
10 | val predictBranch = Bool()
11 | val isPredictValid = Bool()
12 | }
13 |
--------------------------------------------------------------------------------
/src/src/pipeline/simple/bundles/FtqStoreInfoBundle.scala:
--------------------------------------------------------------------------------
1 | package pipeline.simple.bundles
2 |
3 | import chisel3._
4 | import spec._
5 |
6 | class FtqStoreInfoBundle extends Bundle {
7 | val isLastInBlock = Bool()
8 | val ftqId = UInt(Param.BPU.Width.id)
9 | }
10 |
--------------------------------------------------------------------------------
/src/src/pipeline/simple/bundles/InstInfoNdPort.scala:
--------------------------------------------------------------------------------
1 | package pipeline.simple.bundles
2 |
3 | import chisel3._
4 | import control.bundles._
5 | import control.enums.ExceptionPos
6 | import pipeline.common.bundles._
7 | import spec.ExeInst.OpBundle
8 | import spec.Param.isDiffTest
9 | import spec._
10 |
11 | class InstInfoNdPort extends Bundle {
12 | val pc = if (isDiffTest) Some(UInt(Width.Reg.data)) else None
13 | val inst = if (isDiffTest) Some(UInt(Width.Reg.data)) else None
14 | val isValid = Bool()
15 | val exceptionPos = ExceptionPos()
16 | val exceptionRecord = UInt(Csr.ExceptionIndex.width)
17 | val needRefetch = Bool()
18 | val isCsrWrite = Bool()
19 |
20 | val exeOp = new OpBundle
21 | val robId = UInt(Param.Width.Rob.id)
22 |
23 | val load = if (isDiffTest) Some(new DifftestLoadNdPort) else None
24 | val store = if (isDiffTest) Some(new DifftestStoreNdPort) else None
25 | val tlbFill = if (isDiffTest) Some(new DifftestTlbFillNdPort) else None
26 | val timerInfo = if (isDiffTest) Some(new DifftestTimerNdPort) else None
27 | val ftqInfo = new FtqStoreInfoBundle
28 | val ftqCommitInfo = new CommitFtqInfoBundle
29 |
30 | val isTlb = Bool()
31 |
32 | val forbidParallelCommit = Bool()
33 | }
34 |
35 | object InstInfoNdPort {
36 | def default = 0.U.asTypeOf(new InstInfoNdPort)
37 |
38 | def invalidate(instInfo: InstInfoNdPort): Unit = {
39 | instInfo.isValid := false.B
40 | instInfo.needRefetch := false.B
41 | instInfo.exceptionPos := ExceptionPos.none
42 | instInfo.exeOp := ExeInst.Op.nop
43 | instInfo.isCsrWrite := false.B
44 | instInfo.isTlb := false.B
45 | instInfo.forbidParallelCommit := false.B
46 |
47 | if (isDiffTest) {
48 | instInfo.load.get.en := false.B
49 | instInfo.store.get.en := false.B
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/src/pipeline/simple/bundles/MainExeBranchInfoBundle.scala:
--------------------------------------------------------------------------------
1 | package pipeline.simple.bundles
2 |
3 | import chisel3._
4 | import spec._
5 |
6 | class MainExeBranchInfoBundle extends Bundle {
7 | val isBranch = Bool()
8 | val branchType = UInt(Param.BPU.BranchType.width.W)
9 | val fallThroughPc = UInt(Width.Reg.data)
10 | val predictSubImm = UInt(Width.Reg.data)
11 | val predictJumpAddr = UInt(Width.Reg.data)
12 | val fallThroughPredictCorrect = Bool()
13 | val immPredictCorrect = Bool()
14 | val ftqPredictInfo = new FtqPredictInfoBundle
15 | }
16 |
--------------------------------------------------------------------------------
/src/src/pipeline/simple/bundles/PreExeInstNdPort.scala:
--------------------------------------------------------------------------------
1 | package pipeline.simple.bundles
2 |
3 | import chisel3._
4 | import common.bundles.RfAccessInfoNdPort
5 | import spec.ExeInst.OpBundle
6 | import spec._
7 |
8 | class PreExeInstNdPort(readNum: Int = Param.instRegReadNum) extends Bundle {
9 | // Micro-instruction for execution stage
10 | val exeOp = new OpBundle
11 |
12 | // GPR read (`readNum`)
13 | val gprReadPorts = Vec(readNum, new RfAccessInfoNdPort)
14 | val csrReadEn = Bool()
15 | val csrWriteEn = Bool()
16 |
17 | // GPR write
18 | val gprWritePort = new RfAccessInfoNdPort
19 |
20 | // Immediate
21 | val isHasImm = Bool()
22 | val imm = UInt(Width.Reg.data)
23 |
24 | // Branch jump addr
25 | val jumpBranchAddr = UInt(Width.Reg.data)
26 |
27 | def loadStoreImm = jumpBranchAddr
28 | def csrAddr = jumpBranchAddr
29 | def code = jumpBranchAddr
30 | def tlbInvalidateInst = jumpBranchAddr
31 |
32 | val needRefetch = Bool()
33 | val isTlb = Bool()
34 |
35 | val isIssueMainPipeline = Bool()
36 | val isPrivilege = Bool()
37 | val isBranch = Bool()
38 | val branchType = UInt(Param.BPU.BranchType.width.W)
39 |
40 | val forbidOutOfOrder = Bool()
41 | }
42 |
43 | object PreExeInstNdPort {
44 | def default = 0.U.asTypeOf(new PreExeInstNdPort)
45 | }
46 |
--------------------------------------------------------------------------------
/src/src/pipeline/simple/bundles/RSBundle.scala:
--------------------------------------------------------------------------------
1 | package pipeline.simple.bundles
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import common.bundles.RfAccessInfoNdPort
6 | import pipeline.simple.id.FetchInstDecodeNdPort
7 | import spec._
8 |
9 | class RSBundle extends Bundle {
10 | val decodePort = new FetchInstDecodeNdPort
11 | val regReadResults = Vec(Param.regFileReadNum, Valid(UInt(Width.Reg.data)))
12 | }
13 |
14 | object RSBundle {
15 | val default = 0.U.asTypeOf(new RSBundle)
16 | }
17 |
18 | class MainRSBundle extends RSBundle {
19 | val mainExeBranchInfo = new MainExeBranchInfoBundle
20 | }
21 |
22 | class RSBundle2 extends Bundle {
23 | val instInfo = new InstInfoNdPort
24 | val gprReadPorts = Vec(Param.regFileReadNum, new RfAccessInfoNdPort)
25 | val gprWritePort = new RfAccessInfoNdPort
26 | val regReadResults = Vec(Param.regFileReadNum, Valid(UInt(Width.Reg.data)))
27 | }
28 |
29 | class MainRSBundle2 extends RSBundle2 {
30 | val mainExeBranchInfo = new MainExeBranchInfoBundle
31 | }
32 |
--------------------------------------------------------------------------------
/src/src/pipeline/simple/bundles/RegMatchBundle.scala:
--------------------------------------------------------------------------------
1 | package pipeline.simple.bundles
2 |
3 | import chisel3._
4 | import pipeline.common.enums.RegDataState
5 | import spec._
6 |
7 | class RegMatchBundle extends Bundle {
8 | val state = RegDataState()
9 | val robId = UInt(Param.Width.Rob.id)
10 | val data = UInt(Width.Reg.data)
11 | }
12 |
13 | object RegMatchBundle {
14 | def default = 0.U.asTypeOf(new RegMatchBundle)
15 | }
16 |
--------------------------------------------------------------------------------
/src/src/pipeline/simple/bundles/RegOccupyNdPort.scala:
--------------------------------------------------------------------------------
1 | package pipeline.simple.bundles
2 |
3 | import chisel3._
4 | import spec.{Param, Width}
5 |
6 | class RegOccupyNdPort extends Bundle {
7 | val en = Bool()
8 | val addr = UInt(Width.Reg.addr)
9 | val robId = UInt(Param.Width.Rob.id)
10 | }
11 |
--------------------------------------------------------------------------------
/src/src/pipeline/simple/bundles/RegReadPort.scala:
--------------------------------------------------------------------------------
1 | package pipeline.simple.bundles
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import spec._
6 |
7 | class RegReadPort extends Bundle {
8 | val addr = Input(UInt(Width.Reg.addr))
9 | val data = Output(Valid(UInt(Width.Reg.data)))
10 | }
11 |
--------------------------------------------------------------------------------
/src/src/pipeline/simple/bundles/RegWakeUpNdPort.scala:
--------------------------------------------------------------------------------
1 | package pipeline.simple.bundles
2 |
3 | import chisel3._
4 | import spec.{Param, Width}
5 |
6 | class RegWakeUpNdPort extends Bundle {
7 | val en = Bool()
8 | val addr = UInt(Width.Reg.addr)
9 | val data = UInt(Width.Reg.data)
10 | val robId = UInt(Param.Width.Rob.id)
11 | }
12 |
13 | object RegWakeUpNdPort {
14 | def default = 0.U.asTypeOf(new RegWakeUpNdPort)
15 | }
16 |
--------------------------------------------------------------------------------
/src/src/pipeline/simple/bundles/RobInstStoreBundle.scala:
--------------------------------------------------------------------------------
1 | package pipeline.simple.bundles
2 |
3 | import chisel3._
4 | import pipeline.common.bundles.PcInstBundle
5 | import pipeline.common.enums.RobInstState
6 |
7 | class RobInstStoreBundle extends Bundle {
8 | val state = RobInstState()
9 | val wbPort = new WbNdPort
10 | val fetchInfo = new PcInstBundle
11 | }
12 |
13 | object RobInstStoreBundle {
14 | def default = 0.U.asTypeOf(new RobInstStoreBundle)
15 | }
16 |
--------------------------------------------------------------------------------
/src/src/pipeline/simple/bundles/RobRequestPort.scala:
--------------------------------------------------------------------------------
1 | package pipeline.simple.bundles
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import pipeline.common.bundles.PcInstBundle
6 | import spec._
7 |
8 | class RobRequestPort extends Bundle {
9 | val request = Input(Valid(new PcInstBundle))
10 | val result = Output(Valid(UInt(Param.Width.Rob.id)))
11 | }
12 |
--------------------------------------------------------------------------------
/src/src/pipeline/simple/bundles/WbNdPort.scala:
--------------------------------------------------------------------------------
1 | package pipeline.simple.bundles
2 |
3 | import chisel3._
4 | import common.bundles.RfWriteNdPort
5 |
6 | class WbNdPort extends Bundle {
7 | val gprWrite = new RfWriteNdPort
8 | val instInfo = new InstInfoNdPort
9 | }
10 |
11 | object WbNdPort {
12 | def default = 0.U.asTypeOf(new WbNdPort)
13 | }
14 |
--------------------------------------------------------------------------------
/src/src/pipeline/simple/decode/BaseDecoder.scala:
--------------------------------------------------------------------------------
1 | package pipeline.simple.decode
2 |
3 | import chisel3._
4 | import pipeline.simple.decode.bundles.DecodePort
5 |
6 | abstract class BaseDecoder extends Module {
7 | // A decoder should:
8 | // 1) Extract and extend immediate from instruction, if it has
9 | // 2) Extract register information from instruction
10 | // 3) Something else...
11 |
12 | val io = IO(new DecodePort)
13 | }
14 |
--------------------------------------------------------------------------------
/src/src/pipeline/simple/decode/Decoder_2R.scala:
--------------------------------------------------------------------------------
1 | package pipeline.simple.decode
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import pipeline.simple.decode.bundles.DecodeOutNdPort
6 | import spec.ExeInst.OpBundle
7 | import spec.Inst.{_2R => Inst}
8 | import spec._
9 |
10 | class Decoder_2R extends BaseDecoder {
11 | io.out := DecodeOutNdPort.default
12 |
13 | val opcode = WireDefault(io.instInfoPort.inst(31, 10))
14 | val rj = WireDefault(io.instInfoPort.inst(9, 5))
15 | val rd = WireDefault(io.instInfoPort.inst(4, 0))
16 | val rdIsNotZero = WireDefault(rd.orR)
17 |
18 | io.out.info.isHasImm := false.B
19 |
20 | switch(opcode) {
21 | is(Inst.rdcnt_id_vl) {
22 | io.out.info.isIssueMainPipeline := true.B
23 | io.out.isMatched := true.B
24 | when(rj.orR) {
25 | io.out.info.csrReadEn := true.B
26 | io.out.info.csrAddr := Csr.Index.tid
27 | io.out.info.exeOp := OpBundle.csrrd
28 | io.out.info.gprWritePort.en := true.B
29 | io.out.info.gprWritePort.addr := rj
30 | }.otherwise {
31 | io.out.info.gprWritePort.addr := rd
32 | io.out.info.gprWritePort.en := rdIsNotZero
33 | io.out.info.exeOp := OpBundle.rdcntvl_w
34 | }
35 | }
36 | is(Inst.rdcnt_vh) {
37 | io.out.info.isIssueMainPipeline := true.B
38 | io.out.isMatched := true.B
39 | io.out.info.gprWritePort.en := rdIsNotZero
40 | io.out.info.gprWritePort.addr := rd
41 | io.out.info.exeOp := OpBundle.rdcntvh_w
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/src/pipeline/simple/decode/bundles/DecodeOutNdPort.scala:
--------------------------------------------------------------------------------
1 | package pipeline.simple.decode.bundles
2 |
3 | import chisel3._
4 | import pipeline.simple.bundles.PreExeInstNdPort
5 |
6 | class DecodeOutNdPort extends Bundle {
7 | // Is instruction matched
8 | val isMatched = Bool()
9 | val info = new PreExeInstNdPort
10 | }
11 |
12 | object DecodeOutNdPort {
13 | def default = 0.U.asTypeOf(new DecodeOutNdPort)
14 | }
15 |
--------------------------------------------------------------------------------
/src/src/pipeline/simple/decode/bundles/DecodePort.scala:
--------------------------------------------------------------------------------
1 | package pipeline.simple.decode.bundles
2 |
3 | import chisel3._
4 | import pipeline.common.bundles.FetchInstInfoBundle
5 |
6 | class DecodePort extends Bundle {
7 | // The original instruction
8 | val instInfoPort = Input(new FetchInstInfoBundle)
9 |
10 | // Output info
11 | val out = Output(new DecodeOutNdPort)
12 | }
13 |
--------------------------------------------------------------------------------
/src/src/pipeline/simple/id/BaseIssueQueue.scala:
--------------------------------------------------------------------------------
1 | package pipeline.simple.id
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import frontend.bundles.QueryPcBundle
6 | import pipeline.simple.{ExeNdPort, MainExeNdPort}
7 | import pipeline.simple.bundles.{RegOccupyNdPort, RegReadPort, RegWakeUpNdPort}
8 | import pipeline.simple.pmu.bundles.PmuDispatchInfoBundle
9 | import spec._
10 | import pipeline.simple.decode.bundles.DecodeOutNdPort
11 | import pipeline.simple.bundles.InstInfoNdPort
12 |
13 | class FetchInstDecodeNdPort extends Bundle {
14 | val decode = new DecodeOutNdPort
15 | val instInfo = new InstInfoNdPort
16 | // val fetchInfo = new PcInstBundle
17 | }
18 |
19 | object FetchInstDecodeNdPort {
20 | def default = 0.U.asTypeOf(new FetchInstDecodeNdPort)
21 | }
22 |
23 | abstract class BaseIssueQueue(
24 | issueNum: Int = Param.issueInstInfoMaxNum,
25 | pipelineNum: Int = Param.pipelineNum)
26 | extends Module {
27 | val io = IO(new Bundle {
28 | val isFlush = Input(Bool())
29 | val ins = Vec(
30 | issueNum,
31 | Flipped(Decoupled(new RegReadNdPort))
32 | )
33 |
34 | val dequeuePorts = new Bundle {
35 | val mainExePort = Decoupled(new MainExeNdPort)
36 | val simpleExePorts = Vec(pipelineNum - 1, Decoupled(new ExeNdPort))
37 | }
38 |
39 | val queryPcPort = Flipped(new QueryPcBundle)
40 |
41 | val regReadPorts = Vec(Param.issueInstInfoMaxNum, Vec(Param.regFileReadNum, Flipped(new RegReadPort)))
42 | val occupyPorts = Output(Vec(Param.issueInstInfoMaxNum, new RegOccupyNdPort))
43 |
44 | val wakeUpPorts = Input(Vec(pipelineNum + 1, new RegWakeUpNdPort))
45 | val pmu_dispatchInfos = Option.when(Param.usePmu)(Output(Vec(Param.pipelineNum, new PmuDispatchInfoBundle)))
46 |
47 | })
48 | }
49 |
--------------------------------------------------------------------------------
/src/src/pipeline/simple/id/DecodeUnit.scala:
--------------------------------------------------------------------------------
1 | package pipeline.simple.id
2 |
3 | import chisel3._
4 | import pipeline.common.bundles.FetchInstInfoBundle
5 | import pipeline.simple.bundles.PreExeInstNdPort
6 | import pipeline.simple.decode._
7 | import pipeline.simple.decode.bundles.DecodeOutNdPort
8 | import utils.MultiMux1
9 |
10 | class DecodeUnit extends Module {
11 | val io = IO(new Bundle {
12 | val in = Input(new FetchInstInfoBundle)
13 | val out = Output(new DecodeOutNdPort)
14 | })
15 |
16 | val decoders =
17 | Seq(
18 | Module(new Decoder_2RI12),
19 | Module(new Decoder_2RI14),
20 | Module(new Decoder_2RI16),
21 | Module(new Decoder_2R),
22 | Module(new Decoder_3R),
23 | Module(new Decoder_special)
24 | )
25 |
26 | decoders.foreach(_.io.instInfoPort := io.in)
27 |
28 | val mux = Module(new MultiMux1(decoders.length, new PreExeInstNdPort, PreExeInstNdPort.default))
29 | mux.io.inputs.zip(decoders).foreach {
30 | case (dst, src) =>
31 | dst.valid := src.io.out.isMatched
32 | dst.bits := src.io.out.info
33 | }
34 |
35 | io.out.isMatched := mux.io.output.valid
36 | io.out.info := mux.io.output.bits
37 | }
38 |
--------------------------------------------------------------------------------
/src/src/pipeline/simple/id/SimpleInstQueue.scala:
--------------------------------------------------------------------------------
1 | package pipeline.simple.id
2 |
3 | import chisel3._
4 | import chisel3.util._
5 | import common.DistributedQueue
6 | import pipeline.common.bundles.{FetchInstInfoBundle, InstQueueEnqNdPort}
7 | import spec._
8 |
9 | class SimpleInstQueue(
10 | queueLength: Int = Param.instQueueLength,
11 | channelNum: Int = Param.instQueueChannelNum,
12 | fetchNum: Int = Param.fetchInstMaxNum,
13 | issueNum: Int = Param.issueInstInfoMaxNum)
14 | extends Module {
15 | val io = IO(new Bundle {
16 | val isFlush = Input(Bool())
17 | val enqueuePort = Flipped(Decoupled(new InstQueueEnqNdPort))
18 |
19 | // `InstQueue` -> `IssueStage`
20 | val dequeuePorts = Vec(
21 | issueNum,
22 | Decoupled(new FetchInstInfoBundle)
23 | )
24 | })
25 |
26 | require(queueLength > fetchNum)
27 | require(queueLength > issueNum)
28 | require(channelNum >= fetchNum)
29 | require(channelNum >= issueNum)
30 | require(queueLength % channelNum == 0)
31 |
32 | val instQueue = Module(
33 | new DistributedQueue(
34 | fetchNum,
35 | issueNum,
36 | channelNum,
37 | queueLength / channelNum,
38 | new FetchInstInfoBundle,
39 | flow = !Param.instQueueCombineSel
40 | )
41 | )
42 |
43 | instQueue.io.enqueuePorts.zipWithIndex.foreach {
44 | case (enq, idx) =>
45 | enq.valid := io.enqueuePort.bits.enqInfos(idx).valid && io.enqueuePort.ready && io.enqueuePort.valid
46 | enq.bits := io.enqueuePort.bits.enqInfos(idx).bits
47 | }
48 | io.enqueuePort.ready := instQueue.io.enqueuePorts.map(_.ready).reduce(_ && _)
49 | instQueue.io.isFlush := io.isFlush
50 |
51 | io.dequeuePorts.zip(instQueue.io.dequeuePorts).foreach {
52 | case (dst, src) =>
53 | dst <> src
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/src/src/pipeline/simple/pmu/bundles/PmuBranchMisPredictExeNdPort.scala:
--------------------------------------------------------------------------------
1 | package pipeline.simple.pmu.bundles
2 |
3 | import chisel3._
4 |
5 | class PmuBranchMisPredictExeNdPort extends Bundle {
6 | val directionMispredict = Bool()
7 | val targetMispredict = Bool()
8 | }
9 |
--------------------------------------------------------------------------------
/src/src/pipeline/simple/pmu/bundles/PmuBranchPredictNdPort.scala:
--------------------------------------------------------------------------------
1 | package pipeline.simple.pmu.bundles
2 |
3 | import chisel3._
4 | import spec._
5 |
6 | class PmuBranchPredictNdPort extends Bundle {
7 | val isBranch = Bool()
8 | val isRedirect = Bool()
9 | val branchType = UInt(Param.BPU.BranchType.width.W)
10 | val directionMispredict = Bool()
11 | val targetMispredict = Bool()
12 | }
13 |
--------------------------------------------------------------------------------
/src/src/pipeline/simple/pmu/bundles/PmuCacheNdPort.scala:
--------------------------------------------------------------------------------
1 | package pipeline.simple.pmu.bundles
2 |
3 | import chisel3._
4 |
5 | class PmuCacheNdPort extends Bundle {
6 | val newReq = Bool()
7 | val cacheHit = Bool()
8 | val cacheMiss = Bool()
9 | val lineReplace = Bool()
10 | }
11 |
--------------------------------------------------------------------------------
/src/src/pipeline/simple/pmu/bundles/PmuDispatchInfoBundle.scala:
--------------------------------------------------------------------------------
1 | package pipeline.simple.pmu.bundles
2 |
3 | import chisel3._
4 |
5 | class PmuDispatchInfoBundle extends Bundle {
6 | val bubbleFromBackend = Bool()
7 | val bubbleFromFrontend = Bool()
8 | val bubbleFromDataDependence = Bool()
9 | val isIssueInst = Bool()
10 | }
11 |
--------------------------------------------------------------------------------
/src/src/utils/BiCounter.scala:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import chisel3._
4 | import chisel3.util._
5 |
6 | class BiCounter(count: Int, init: Int = 0) extends Module {
7 | require(count > 1)
8 | val w = log2Ceil(count).W
9 | val io = IO(new Bundle {
10 | // inc =/= `11`
11 | val inc = Input(UInt(2.W))
12 | val flush = Input(Bool())
13 | // one clock delay
14 | val value = Output(UInt(w))
15 | // no delay
16 | val incOneResult = Output(UInt(w))
17 | val incTwoResult = Output(UInt(w))
18 | })
19 |
20 | val counter = RegInit(init.U(w))
21 | val incOneResult = WireDefault(0.U(w))
22 | val incTwoResult = WireDefault(0.U(w))
23 | io.incOneResult := incOneResult
24 | io.incTwoResult := incTwoResult
25 | io.value := counter
26 |
27 | // when(io.inc === 1.U) {
28 | when(counter === (count - 1).U) {
29 | incOneResult := 0.U
30 | }.otherwise {
31 | incOneResult := counter + 1.U
32 | }
33 | // }.elsewhen(io.inc === 2.U) {
34 | when(counter === (count - 2).U) {
35 | incTwoResult := 0.U
36 | }.elsewhen(counter === (count - 1).U) {
37 | incTwoResult := 1.U
38 | }.otherwise {
39 | incTwoResult := counter + 2.U
40 | }
41 | // }
42 | when(io.inc === 1.U) {
43 | counter := incOneResult
44 | }.elsewhen(io.inc === 2.U) {
45 | counter := incTwoResult
46 | }
47 |
48 | when(io.flush) {
49 | io.value := 0.U
50 | counter := 0.U
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/src/utils/BiPriorityMux.scala:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import chisel3._
4 | import chisel3.util.log2Ceil
5 |
6 | // 串行太多啦,待并行优化
7 | class BiPriorityMux(num: Int = 8) extends Module {
8 | val numLog = log2Ceil(num)
9 | val io = IO(new Bundle {
10 | val inVector = Input(Vec(num, Bool()))
11 | val selectIndices = Output(
12 | Vec(
13 | 2,
14 | new Bundle {
15 | val valid = Bool()
16 | val index = UInt(numLog.W)
17 | }
18 | )
19 | )
20 | })
21 |
22 | io.selectIndices.foreach { selectIndex =>
23 | selectIndex.valid := false.B
24 | selectIndex.index := 0.U
25 | }
26 | for (i <- 0 until num) {
27 | when(io.inVector(i)) {
28 | io.selectIndices(0).valid := true.B
29 | io.selectIndices(0).index := i.U
30 | }
31 | }
32 |
33 | for (i <- 0 until num) {
34 | when(io.inVector(i) && (i.U =/= io.selectIndices(0).index)) {
35 | io.selectIndices(1).valid := true.B
36 | io.selectIndices(1).index := i.U
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/src/utils/MinFinder.scala:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import chisel3._
4 | import chisel3.util._
5 |
6 | class MinFinder(num: Int, wordLength: Int) extends Module {
7 | val numLog = log2Ceil(num)
8 | val io = IO(new Bundle {
9 | val values = Input(Vec(num, UInt(wordLength.W)))
10 | val masks = Input(Vec(num, Bool()))
11 | val index = Output(UInt(numLog.W))
12 | })
13 |
14 | // word length * num
15 | val compareVec = VecInit(Seq.range(0, wordLength).map { bitNum =>
16 | VecInit(io.values.map(_(bitNum))).asUInt
17 | })
18 |
19 | val flags = VecInit(compareVec.scanRight(io.masks.asUInt)((now, high) => {
20 | val tmp = (~high | now)
21 | Mux(
22 | tmp.andR,
23 | high,
24 | ~tmp
25 | )
26 | }))
27 |
28 | io.index := 0.U
29 | flags(0).asBools.zipWithIndex.foreach {
30 | case (flag, index) =>
31 | when(flag) {
32 | io.index := index.U
33 | }
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/src/src/utils/MultiCounter.scala:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import chisel3._
4 | import chisel3.util._
5 |
6 | class MultiCounter(
7 | maxCount: Int,
8 | maxIncNum: Int,
9 | init: Int = 0,
10 | supportSet: Boolean = false,
11 | needRecurrent: Boolean = true)
12 | extends Module {
13 | require(maxCount >= maxIncNum)
14 | val value_w = log2Ceil(maxCount)
15 | val inc_w = log2Ceil(maxIncNum + 1)
16 |
17 | val isMaxCountPow2: Boolean = isPow2(maxCount)
18 |
19 | val io = IO(new Bundle {
20 | // inc =/= `11`
21 | val inc = Input(UInt(inc_w.W))
22 | val flush = Input(Bool())
23 | // one clock delay
24 | val value = Output(UInt(value_w.W))
25 | // no delay
26 | val incResults = Output(Vec(maxCount + 1, UInt(value_w.W)))
27 |
28 | val setPort = if (supportSet) Some(Input(Valid(UInt(value_w.W)))) else None
29 | })
30 |
31 | val counter = RegInit(init.U(value_w.W))
32 | val incResults = Wire(Vec(maxCount + 1, UInt(value_w.W)))
33 | io.value := counter
34 | io.incResults.zip(incResults).foreach {
35 | case (dst, src) =>
36 | dst := src
37 | }
38 |
39 | incResults.zipWithIndex.foreach {
40 | case (incResult, inc) =>
41 | if (isMaxCountPow2 || !needRecurrent) {
42 | incResult := counter + inc.U
43 | } else {
44 | val rawAdd = Wire(UInt((value_w + 1).W))
45 | rawAdd := counter +& inc.U
46 | incResult := Mux(
47 | rawAdd >= maxCount.U,
48 | rawAdd - maxCount.U, // 溢出
49 | rawAdd
50 | )
51 | }
52 | }
53 |
54 | counter := incResults(io.inc)
55 |
56 | if (supportSet) {
57 | when(io.setPort.get.valid) {
58 | counter := io.setPort.get.bits
59 | }
60 | }
61 |
62 | when(io.flush) {
63 | io.value := init.U
64 | counter := init.U
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/src/utils/MultiMux.scala:
--------------------------------------------------------------------------------
1 | package utils
2 | import chisel3._
3 | import chisel3.util._
4 |
5 | // 必须保证input只有一个valid
6 | class MultiMux1[T <: Data](length: Int, tFactory: => T, blankT: => T) extends Module {
7 | val io = IO(new Bundle {
8 | val inputs = Input(Vec(length, Valid(tFactory)))
9 | val output = Valid(tFactory)
10 | })
11 |
12 | io.output.valid := io.inputs.map(_.valid).reduce(_ || _)
13 | val flatten = Wire(Vec(length, tFactory))
14 | for (i <- 0 until length) {
15 | flatten(i) := Mux(io.inputs(i).valid, io.inputs(i).bits, blankT)
16 | }
17 | io.output.bits := VecInit(flatten.map(_.asUInt)).reduceTree(_ | _).asTypeOf(tFactory)
18 | }
19 |
20 | class MultiMux2[T <: Data](length1: Int, length2: Int, tFactory: => T, blankT: => T) extends Module {
21 | val io = IO(new Bundle {
22 | val inputs = Input(Vec(length1, Vec(length2, Valid(tFactory))))
23 | val output = Valid(tFactory)
24 | })
25 |
26 | io.output.valid := io.inputs.map(_.map(_.valid).reduce(_ || _)).reduce(_ || _)
27 | val flatten = Wire(Vec(length1 * length2, tFactory))
28 | for (i <- 0 until length1) {
29 | for (j <- 0 until length2) {
30 | flatten(i * length2 + j) := Mux(io.inputs(i)(j).valid, io.inputs(i)(j).bits, blankT)
31 | }
32 | }
33 | io.output.bits := VecInit(flatten.map(_.asUInt)).reduceTree(_ | _).asTypeOf(tFactory)
34 | }
35 |
--------------------------------------------------------------------------------
/src/test/src/ComponentSpec.scala:
--------------------------------------------------------------------------------
1 | // import chisel3._
2 | // import chisel3.experimental.BundleLiterals.AddBundleLiteralConstructor
3 | // import chiseltest._
4 | // import chiseltest.simulator.WriteVcdAnnotation
5 | // import pipeline.dispatch.bundles.FetchInstInfoBundle
6 | // import pipeline.queue.InstQueue
7 | // import utest._
8 |
9 | // object ComponentSpec extends ChiselUtestTester {
10 | // val tests = Tests {
11 | // test("Test InstQueue module") {
12 | // testCircuit(new InstQueue, immutable.Seq(WriteVcdAnnotation)) { instQueue =>
13 | // // Nothing in queue, then no dequeue
14 | // instQueue.io.dequeuePort.valid.expect(false.B)
15 | // instQueue.io.enqueuePort.ready.expect(true.B)
16 | // instQueue.clock.step()
17 |
18 | // // Enqueue and dequeue at the same time, then flow through and can dequeue
19 | // val testValue = (new InstInfoBundle).Lit(
20 | // _.pcAddr -> 114.U,
21 | // _.inst -> 514.U
22 | // )
23 | // instQueue.io.enqueuePort.ready.expect(true.B)
24 | // instQueue.io.enqueuePort.valid.poke(true.B)
25 | // instQueue.io.enqueuePort.bits.poke(testValue)
26 |
27 | // instQueue.io.dequeuePort.ready.poke(true.B)
28 | // instQueue.io.dequeuePort.valid.expect(true.B)
29 | // instQueue.io.dequeuePort.bits.expect(testValue)
30 | // instQueue.clock.step()
31 |
32 | // // Fill up the queue, then cannot enqueue
33 | // instQueue.io.dequeuePort.ready.poke(false.B)
34 | // for (i <- 1 to 5) {
35 | // instQueue.io.enqueuePort.valid.poke(true.B)
36 | // instQueue.io.enqueuePort.bits.poke(testValue)
37 | // instQueue.clock.step()
38 | // }
39 | // instQueue.io.enqueuePort.valid.poke(false.B)
40 | // instQueue.io.enqueuePort.ready.expect(false.B)
41 |
42 | // // Flush the queue, then cannot dequeue
43 | // // instQueue.io.isFlush.poke(true.B)
44 | // instQueue.io.pipelineControlPort.flush.poke(true.B)
45 | // instQueue.clock.step()
46 | // instQueue.io.dequeuePort.valid.expect(false.B)
47 | // }
48 | // }
49 | // }
50 | // }
51 |
--------------------------------------------------------------------------------
/src/test/src/DataForwardSpec.scala:
--------------------------------------------------------------------------------
1 | // import chisel3._
2 | // import chisel3.experimental.BundleLiterals.AddBundleLiteralConstructor
3 | // import chiseltest._
4 | // import chiseltest.simulator.WriteVcdAnnotation
5 | // import pipeline.dispatch.bundles.FetchInstInfoBundle
6 | // import pipeline.queue.InstQueue
7 | // import utest._
8 |
9 | // import pipeline.dataforward.DataForwardStage
10 |
11 | // object DataForwardSpec extends ChiselUtestTester {
12 | // val tests = Tests {
13 | // test("Test data forward module") {
14 | // testCircuit(new DataForwardStage(3), immutable.Seq(WriteVcdAnnotation)) { dataforward =>
15 | // def wp = dataforward.io.writePorts
16 | // def rp = dataforward.io.readPorts
17 | // rp(0).en.poke(true.B)
18 | // rp(1).en.poke(true.B)
19 | // rp(0).addr.poke(2)
20 | // rp(1).addr.poke(3)
21 |
22 | // wp(0).en .poke(true.B);wp(0).addr.poke(2); wp(0).data.poke(4)
23 | // wp(1).en .poke(true.B);wp(1).addr.poke(2); wp(1).data.poke(6)
24 | // wp(2).en .poke(true.B);wp(2).addr.poke(2); wp(2).data.poke(7)
25 |
26 | // dataforward.clock.step(1)
27 | // wp(0).en .poke(true.B);wp(0).addr.poke(2); wp(0).data.poke(4)
28 | // wp(1).en .poke(true.B);wp(1).addr.poke(3); wp(1).data.poke(6)
29 | // wp(2).en .poke(false.B);wp(2).addr.poke(2); wp(2).data.poke(7)
30 | // dataforward.clock.step(1)
31 | // wp(0).en .poke(false.B);wp(0).addr.poke(2); wp(0).data.poke(4)
32 | // wp(1).en.poke( true.B);wp(1).addr.poke(3); wp(1).data.poke(6)
33 | // wp(2).en.poke( true.B);wp(2).addr.poke(2); wp(2).data.poke(7)
34 | // dataforward.clock.step(1)
35 |
36 | // }
37 | // }
38 | // }
39 | // }
40 |
--------------------------------------------------------------------------------
/src/test/src/ExeStageSpecs/testClz.scala:
--------------------------------------------------------------------------------
1 | // import chisel3._
2 | // import chisel3.util._
3 | // import chisel3.experimental.BundleLiterals.AddBundleLiteralConstructor
4 | // import chiseltest._
5 | // import chiseltest.simulator.WriteVcdAnnotation
6 | // import pipeline.dispatch.bundles.FetchInstInfoBundle
7 | // import utest._
8 | // import pipeline.execution.Clz
9 | // import pipeline.queue.InstQueue
10 | // import scala.util.Random
11 |
12 | // object ComponentSpec extends ChiselUtestTester {
13 | // val tests = Tests {
14 | // test("Test clz module") {
15 | // testCircuit(new Clz, Seq(WriteVcdAnnotation)) { clz =>
16 | // for ( i<- 0 to 30) {
17 | // for (j<-0 to 30) {
18 | // var in = 1
19 | // for(k<-1 until i) {
20 | // in = in * 2 +Random.nextInt(2)
21 | // }
22 | // if (in >= 0) {
23 | // var tmp = in
24 | // var expect = 32
25 | // while (tmp != 0) {
26 | // expect -= 1
27 | // tmp /= 2
28 | // }
29 | // clz.io.input.poke(in.U)
30 | // println(s"${i}: ")
31 | // println(BigInt(in).toString(16))
32 | // print("expect: ")
33 | // println(expect)
34 | // print("res: ")
35 | // println(clz.io.output.peek().litValue)
36 | // println("*************************")
37 | // clz.io.output.expect(expect.U)
38 | // clz.clock.step(1)
39 | // }
40 | // }
41 | // }
42 | // }
43 | // }
44 | // }
45 | // }
46 |
--------------------------------------------------------------------------------
/src/test/src/InstQueueSpec.scala:
--------------------------------------------------------------------------------
1 | // import chisel3._
2 | // import chisel3.experimental.BundleLiterals.AddBundleLiteralConstructor
3 | // import chiseltest._
4 | // import chiseltest.simulator.WriteVcdAnnotation
5 | // import pipeline.dispatch.bundles.FetchInstInfoBundle
6 | // import utest._
7 | // import control.bundles.PipelineControlNdPort
8 | // import pipeline.queue.InstQueue
9 | // import spec.wordLength
10 | // import spec.zeroWord
11 |
12 | // object InstQueueSpec extends ChiselUtestTester {
13 | // val tests = Tests {
14 | // test("Test inst queue") {
15 | // testCircuit(new InstQueue, Seq(WriteVcdAnnotation)) { instQueue =>
16 | // instQueue.io.pipelineControlPort poke PipelineControlNdPort.default
17 | // instQueue.io.enqueuePort.bits.inst.poke(false.B)
18 | // instQueue.io.enqueuePort.bits.pcAddr.poke(false.B)
19 | // val pcs = Seq.range(0,8).map((4*_)).map(_.U)
20 | // val enqSeq = Seq(
21 | // zeroWord,
22 | // "had123456".U(wordLength.W),
23 | // "had234567".U(wordLength.W),
24 | // "had456789".U(wordLength.W),
25 | // "hadaaaaaa".U(wordLength.W),
26 | // "had777777".U(wordLength.W),
27 | // zeroWord,
28 | // zeroWord
29 | // )
30 | // val enqValid = Seq(
31 | // false.B,
32 | // true.B,
33 | // true.B,
34 | // true.B,
35 | // true.B,
36 | // false.B,
37 | // false.B,
38 | // false.B
39 | // )
40 | // val deqReady = Seq(
41 | // false.B,
42 | // false.B,
43 | // false.B,
44 | // true.B,
45 | // true.B,
46 | // true.B,
47 | // true.B,
48 | // true.B,
49 | // )
50 |
51 | // pcs lazyZip enqSeq lazyZip enqValid lazyZip deqReady foreach {case (pc ,bit, in, out) =>
52 | // println ("**************")
53 | // println (pc)
54 | // println (bit)
55 | // println (in)
56 | // println (out)
57 | // instQueue.io.enqueuePort.bits.inst.poke(bit)
58 | // instQueue.io.enqueuePort.bits.pcAddr.poke(pc)
59 | // instQueue.io.enqueuePort.valid.poke(in)
60 | // instQueue.io.dequeuePort.ready.poke(out)
61 | // instQueue.clock.step(1)
62 | // }
63 | // }
64 | // }
65 | // }
66 | // }
67 |
--------------------------------------------------------------------------------
/src/test/src/MultiMuxSpec.scala:
--------------------------------------------------------------------------------
1 | //import chisel3._
2 | //import chisel3.experimental.BundleLiterals.AddBundleLiteralConstructor
3 | //import chiseltest._
4 | //import chiseltest.simulator.WriteVcdAnnotation
5 | //import pipeline.dispatch.bundles.FetchInstInfoBundle
6 | //import pipeline.queue.InstQueue
7 | //import scala.collection.immutable
8 | //import utest._
9 | //import enums.TestEnum
10 | //import utils.MultiMux2
11 | //import chisel3.util.Valid
12 | //
13 | //class TestBundle extends Bundle {
14 | // val ui = UInt(3.W)
15 | // val enum_ = TestEnum()
16 | // val bool = Bool()
17 | //}
18 | //class TestMultiMux extends Module {
19 | //
20 | // val io = IO(new Bundle {
21 | // val input = Input(UInt(4.W))
22 | // val output = Output(Valid(new TestBundle))
23 | // })
24 | //
25 | // def default = 0.U.asTypeOf(new TestBundle)
26 | //
27 | // val mux = Module(new MultiMux2(2, 2, new TestBundle, default))
28 | //
29 | // mux.io.inputs.zipWithIndex.foreach {
30 | // case (mux_1, idx_1) =>
31 | // mux_1.zipWithIndex.foreach {
32 | // case (in, idx_2) =>
33 | // val idx = idx_1 * mux_1.length + idx_2
34 | // in.valid := io.input(idx)
35 | // in.bits.ui := (idx + 1).U
36 | // in.bits.bool := (idx == 0 || idx == 3).B
37 | // idx match {
38 | // case 0 =>
39 | // in.bits.enum_ := TestEnum.a
40 | // case 1 =>
41 | // in.bits.enum_ := TestEnum.c
42 | // case 2 =>
43 | // in.bits.enum_ := TestEnum.b
44 | // case 3 =>
45 | // in.bits.enum_ := TestEnum.a
46 | // }
47 | // }
48 | // }
49 | //
50 | // io.output := mux.io.output
51 | //}
52 | //
53 | //object MultiMuxSpec extends ChiselUtestTester {
54 | // val tests = Tests {
55 | // test("Test multi mux module") {
56 | // testCircuit(new TestMultiMux, immutable.Seq(WriteVcdAnnotation)) { m =>
57 | // m.io.input.poke("b0000".U)
58 | // m.clock.step(1)
59 | // m.io.input.poke("b0001".U)
60 | // m.clock.step(1)
61 | // m.io.input.poke("b0010".U)
62 | // m.clock.step(1)
63 | // m.io.input.poke("b0100".U)
64 | // m.clock.step(1)
65 | // m.io.input.poke("b1000".U)
66 | // m.clock.step(1)
67 | // }
68 | // }
69 | // }
70 | //}
71 |
--------------------------------------------------------------------------------
/src/test/src/SimpleCpuSpec.scala:
--------------------------------------------------------------------------------
1 | // import chisel3._
2 | // import chisel3.experimental.BundleLiterals.AddBundleLiteralConstructor
3 | // import chiseltest._
4 | // import chiseltest.simulator.WriteVcdAnnotation
5 | // import pipeline.dispatch.bundles.FetchInstInfoBundle
6 | // import pipeline.queue.InstQueue
7 | // import utest._
8 |
9 | // object SimpleCpuSpec extends ChiselUtestTester {
10 | // val tests = Tests {
11 | // test("Test instructions") {
12 | // testCircuit(new CoreCpuTop, Seq(WriteVcdAnnotation)) { cpu =>
13 | // val instSeq = Seq(
14 | // "0000001010_000000000011_00000_00001", // addi $1, $0, 3
15 | // "0000001010_000000110011_00000_00100", // addi $4, $0, 51
16 | // "0000001010_000000000010_00001_00010", // addi $2, $1, 2
17 | // // "0000001010_000000000010_00001_00010", // addi $2, $1, 2
18 | // // "00000000001000000_00001_00100_00110", // div $6, $4, $1
19 | // "00000000000100100_00010_00001_00011", // slt $3, $1, $2
20 | // // "00000000000111000_00001_00100_00101", // mul $5, $4, $1
21 | // // "00000000001000000_00001_00100_00110", // div $6, $4, $1
22 | // "00000000000111000_00001_00100_00101", // mul $5, $4, $1
23 | // "00000000001000000_00001_00100_00110", // div $6, $4, $1
24 | // "00000000001000001_00001_00100_00111", // mod $7, $4, $1
25 | // )
26 | // cpu.io.intrpt.poke(0.U)
27 | // cpu.io.axi.arready.poke(true.B)
28 | // cpu.io.axi.rvalid.poke(true.B)
29 | // instSeq.foreach { inst =>
30 | // cpu.io.axi.rdata.poke(("b" + inst).U)
31 | // cpu.clock.step(5)
32 | // }
33 | // cpu.clock.step(15)
34 | // cpu.io.axi.rvalid.poke(false.B)
35 | // cpu.clock.step(15)
36 | // }
37 | // }
38 | // }
39 | // }
40 |
--------------------------------------------------------------------------------
/src/test/src/enums/TestEnum.scala:
--------------------------------------------------------------------------------
1 | //package enums
2 | //
3 | //import chisel3.ChiselEnum
4 | //
5 | //object TestEnum extends ChiselEnum {
6 | // val a, b, c = Value
7 | //}
8 |
--------------------------------------------------------------------------------
/utils/firtool:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ARGS='-O=release --dedup --disable-annotation-unknown --add-vivado-ram-address-conflict-synthesis-bug-workaround --lowering-options disallowLocalVariables'
4 |
5 | # Workaround
6 | for arg do
7 | shift
8 | case $arg in
9 | (-disable-infer-rw) : ;;
10 | (*) set -- "$@" "$arg" ;;
11 | esac
12 | done
13 |
14 | if [[ "$OSTYPE" == "darwin"* ]]; then
15 | firtool_darwin -O=release --dedup --disable-annotation-unknown --add-vivado-ram-address-conflict-synthesis-bug-workaround --lowering-options disallowLocalVariables "$@"
16 | else
17 | firtool_ubuntu2004 -O=release --dedup --disable-annotation-unknown --add-vivado-ram-address-conflict-synthesis-bug-workaround --lowering-options disallowLocalVariables "$@"
18 | fi
19 |
--------------------------------------------------------------------------------
/utils/firtool.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Invalid-Syntax-NSCSCC/invalid-cpu/0f0110a092bac1ba9d7f5196d5cefd1ef9508d51/utils/firtool.exe
--------------------------------------------------------------------------------
/utils/firtool_darwin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Invalid-Syntax-NSCSCC/invalid-cpu/0f0110a092bac1ba9d7f5196d5cefd1ef9508d51/utils/firtool_darwin
--------------------------------------------------------------------------------
/utils/firtool_darwin_x86_64:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Invalid-Syntax-NSCSCC/invalid-cpu/0f0110a092bac1ba9d7f5196d5cefd1ef9508d51/utils/firtool_darwin_x86_64
--------------------------------------------------------------------------------
/utils/firtool_ubuntu2004:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Invalid-Syntax-NSCSCC/invalid-cpu/0f0110a092bac1ba9d7f5196d5cefd1ef9508d51/utils/firtool_ubuntu2004
--------------------------------------------------------------------------------
/verilog/simpledual_readfirst_bram.v:
--------------------------------------------------------------------------------
1 | // Xilinx Simple Dual Port Single Clock RAM
2 | // This code implements a parameterizable SDP single clock memory.
3 | // If a reset or enable is not necessary, it may be tied off or removed from the code.
4 |
5 | module simpledual_readfirst_bram #(
6 | parameter RAM_WIDTH = 1, // Specify RAM data width
7 | parameter RAM_DEPTH = 1, // Specify RAM depth (number of entries)
8 | parameter RAM_PERFORMANCE = "HIGH_PERFORMANCE", // Select "HIGH_PERFORMANCE" or "LOW_LATENCY"
9 | parameter INIT_FILE = "" // Specify name/location of RAM initialization file if using one (leave blank if not)
10 | ) (
11 | input [clogb2(RAM_DEPTH-1)-1:0] addra, // Write address bus, width determined from RAM_DEPTH
12 | input [clogb2(RAM_DEPTH-1)-1:0] addrb, // Read address bus, width determined from RAM_DEPTH
13 | input [RAM_WIDTH-1:0] dina, // RAM input data
14 | input clka, // Clock
15 | input wea, // Write enable
16 | input enb, // Read Enable, for additional power savings, disable when not in use
17 | input rstb, // Output reset (does not affect memory contents)
18 | input regceb, // Output register enable
19 | output [RAM_WIDTH-1:0] doutb // RAM output data
20 | );
21 |
22 | reg [RAM_WIDTH-1:0] BRAM [RAM_DEPTH-1:0];
23 | reg [RAM_WIDTH-1:0] ram_data = {RAM_WIDTH{1'b0}};
24 |
25 | // The following code either initializes the memory values to a specified file or to all zeros to match hardware
26 | generate
27 | if (INIT_FILE != "") begin: use_init_file
28 | initial
29 | $readmemh(INIT_FILE, BRAM, 0, RAM_DEPTH-1);
30 | end else begin: init_bram_to_zero
31 | integer ram_index;
32 | initial
33 | for (ram_index = 0; ram_index < RAM_DEPTH; ram_index = ram_index + 1)
34 | BRAM[ram_index] = {RAM_WIDTH{1'b0}};
35 | end
36 | endgenerate
37 |
38 | always @(posedge clka) begin
39 | if (wea)
40 | BRAM[addra] <= dina;
41 | if (enb)
42 | ram_data <= BRAM[addrb];
43 | end
44 |
45 | // The following code generates HIGH_PERFORMANCE (use output register) or LOW_LATENCY (no output register)
46 | generate
47 | if (RAM_PERFORMANCE == "LOW_LATENCY") begin: no_output_register
48 |
49 | // The following is a 1 clock cycle read latency at the cost of a longer clock-to-out timing
50 | assign doutb = ram_data;
51 |
52 | end else begin: output_register
53 |
54 | // The following is a 2 clock cycle read latency with improve clock-to-out timing
55 |
56 | reg [RAM_WIDTH-1:0] doutb_reg = {RAM_WIDTH{1'b0}};
57 |
58 | always @(posedge clka)
59 | if (rstb)
60 | doutb_reg <= {RAM_WIDTH{1'b0}};
61 | else if (regceb)
62 | doutb_reg <= ram_data;
63 |
64 | assign doutb = doutb_reg;
65 |
66 | end
67 | endgenerate
68 |
69 | // The following function calculates the address width based on specified RAM depth
70 | function integer clogb2;
71 | input integer depth;
72 | for (clogb2=0; depth>0; clogb2=clogb2+1)
73 | depth = depth >> 1;
74 | endfunction
75 |
76 | endmodule
--------------------------------------------------------------------------------