forked from XS-MLVP/UnityChipForXiangShan
Compare commits
1 Commits
main
...
ftq_env_pa
| Author | SHA1 | Date |
|---|---|---|
|
|
8205745eec |
|
|
@ -18,7 +18,7 @@ weight: 13
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/XS-MLVP/UnityChipForXiangShan.git
|
git clone https://github.com/XS-MLVP/UnityChipForXiangShan.git
|
||||||
cd UnityChipForXiangShan
|
cd UnityChipForXiangShan
|
||||||
pip3 install -r requirements.txt # 安装 python 依赖(例如 toffee)
|
pip3 install -r requirements.txt # 安装python依赖(例如 toffee)
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 下载RTL代码:
|
#### 下载RTL代码:
|
||||||
|
|
@ -26,10 +26,10 @@ pip3 install -r requirements.txt # 安装 python 依赖(例如 toffee)
|
||||||
默认从仓库[https://github.com/XS-MLVP/UnityChipXiangShanRTLs](https://github.com/XS-MLVP/UnityChipXiangShanRTLs)中下载。用户也可以自行按照XiangShan文档编译生成RTL。
|
默认从仓库[https://github.com/XS-MLVP/UnityChipXiangShanRTLs](https://github.com/XS-MLVP/UnityChipXiangShanRTLs)中下载。用户也可以自行按照XiangShan文档编译生成RTL。
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
make rtl # 该命令下载最新的 rtl 代码,解压至 rtl 目录,并创建软链接
|
make rtl # 该命下载最新的rtl代码,并解压至rtl目录,并创建软连接
|
||||||
```
|
```
|
||||||
|
|
||||||
可以用以下命令指定下载的 rtl 版本:
|
可以用以下命令指定下载的rtl版本:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
make rtl args="rtl.version=\'openxiangshan-kmh-fad7803d-24120901\'"
|
make rtl args="rtl.version=\'openxiangshan-kmh-fad7803d-24120901\'"
|
||||||
|
|
@ -37,7 +37,7 @@ make rtl args="rtl.version=\'openxiangshan-kmh-fad7803d-24120901\'"
|
||||||
|
|
||||||
所有RTL下载包请在[UnityChipXiangShanRTLs](https://github.com/XS-MLVP/UnityChipXiangShanRTLs)中查看。
|
所有RTL下载包请在[UnityChipXiangShanRTLs](https://github.com/XS-MLVP/UnityChipXiangShanRTLs)中查看。
|
||||||
|
|
||||||
RTL压缩包的命名规范为:`名称-微架构-Git标记-日期编号.tar.gz`,例如`openxiangshan-kmh-97e37a2237-24092701.tar.gz`。在使用时,仓库代码会过滤掉 git 标记和后缀,例如通过 cfg.rtl.version 访问到的版本号为:`openxiangshan-kmh-24092701`。压缩包内的目录结构为:
|
RTL压缩包的命名规范为:`名称-微架构-Git标记-日期编号.tar.gz`,例如`openxiangshan-kmh-97e37a2237-24092701.tar.gz`。在使用时,仓库代码会过滤掉git标记和后缀,例如通过 cfg.rtl.version 访问到的版本号为:`openxiangshan-kmh-24092701`。压缩包内的目录结构为:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
openxiangshan-kmh-97e37a2237-24092701.tar.gz
|
openxiangshan-kmh-97e37a2237-24092701.tar.gz
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ def get_metadata():
|
||||||
"dut_name": "frontend_instruncache",
|
"dut_name": "frontend_instruncache",
|
||||||
"dut_dir": "InstrUncache",
|
"dut_dir": "InstrUncache",
|
||||||
"test_targets": [
|
"test_targets": [
|
||||||
"ut_frontend/instruncache/classic_version",
|
"ut_frontend/instruncache/classical_version",
|
||||||
"ut_frontend/instruncache/toffee_version",
|
"ut_frontend/instruncache/toffee_version",
|
||||||
"ut_frontend/instruncache",
|
"ut_frontend/instruncache",
|
||||||
"ut_frontend"
|
"ut_frontend"
|
||||||
|
|
|
||||||
|
|
@ -3,4 +3,3 @@ ICacheMainPipe:
|
||||||
- "wire _toMSHRArbiter_io_in_0_valid_T_4"
|
- "wire _toMSHRArbiter_io_in_0_valid_T_4"
|
||||||
- "wire _toMSHRArbiter_io_in_1_valid_T_4"
|
- "wire _toMSHRArbiter_io_in_1_valid_T_4"
|
||||||
- "reg s2_valid"
|
- "reg s2_valid"
|
||||||
- "wire s0_fire"
|
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,6 @@ async def ctrlunit_env(toffee_request: toffee_test.ToffeeRequest):
|
||||||
dut.InitClock("clock")
|
dut.InitClock("clock")
|
||||||
start_clock(dut)
|
start_clock(dut)
|
||||||
ctrlunit_env = CtrlUnitEnv(dut)
|
ctrlunit_env = CtrlUnitEnv(dut)
|
||||||
ctrlunit_env.dut.reset.value = 1
|
|
||||||
ctrlunit_env.dut.Step(10)
|
|
||||||
ctrlunit_env.dut.reset.value = 0
|
|
||||||
ctrlunit_env.dut.Step(10)
|
|
||||||
yield ctrlunit_env
|
yield ctrlunit_env
|
||||||
|
|
||||||
cur_loop = asyncio.get_event_loop()
|
cur_loop = asyncio.get_event_loop()
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,6 @@ async def icache_env(toffee_request: toffee_test.ToffeeRequest):
|
||||||
dut.InitClock("clock")
|
dut.InitClock("clock")
|
||||||
start_clock(dut)
|
start_clock(dut)
|
||||||
icache_env = ICacheEnv(dut)
|
icache_env = ICacheEnv(dut)
|
||||||
icache_env.dut.reset.value = 1
|
|
||||||
icache_env.dut.Step(10)
|
|
||||||
icache_env.dut.reset.value = 0
|
|
||||||
icache_env.dut.Step(10)
|
|
||||||
yield icache_env
|
yield icache_env
|
||||||
|
|
||||||
cur_loop = asyncio.get_event_loop()
|
cur_loop = asyncio.get_event_loop()
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,21 @@ class IPrefetchPipeAgent(Agent):
|
||||||
super().__init__(bundle)
|
super().__init__(bundle)
|
||||||
self.bundle = bundle
|
self.bundle = bundle
|
||||||
|
|
||||||
|
async def set_s1_flush(self):
|
||||||
|
self.bundle.reset.value = 1
|
||||||
|
await self.bundle.step()
|
||||||
|
self.bundle.reset.value = 0
|
||||||
|
await self.bundle.step()
|
||||||
|
|
||||||
|
print(
|
||||||
|
"\nBefore setting, s1_flush is: ",
|
||||||
|
self.bundle.IPrefetchPipe._s1._flush.value,
|
||||||
|
)
|
||||||
|
self.bundle.io._flush.value = 1
|
||||||
|
await self.bundle.step()
|
||||||
|
print(
|
||||||
|
"After setting, s1_flush is: ", self.bundle.IPrefetchPipe._s1._flush.value
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def receive_prefetch(self):
|
async def receive_prefetch(self):
|
||||||
|
|
|
||||||
|
|
@ -14,10 +14,6 @@ async def iprefetchpipe_env(toffee_request: toffee_test.ToffeeRequest):
|
||||||
start_clock(dut)
|
start_clock(dut)
|
||||||
iprefetchpipe_env = IPrefetchPipeEnv(dut)
|
iprefetchpipe_env = IPrefetchPipeEnv(dut)
|
||||||
toffee_request.add_cov_groups([get_cover_group_of_receive_prefetch_quest(dut)])
|
toffee_request.add_cov_groups([get_cover_group_of_receive_prefetch_quest(dut)])
|
||||||
iprefetchpipe_env.dut.reset.value = 1
|
|
||||||
iprefetchpipe_env.dut.Step(10)
|
|
||||||
iprefetchpipe_env.dut.reset.value = 0
|
|
||||||
iprefetchpipe_env.dut.Step(10)
|
|
||||||
yield iprefetchpipe_env
|
yield iprefetchpipe_env
|
||||||
|
|
||||||
cur = asyncio.get_event_loop()
|
cur = asyncio.get_event_loop()
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,10 @@ from ..env import IPrefetchPipeEnv
|
||||||
import toffee_test
|
import toffee_test
|
||||||
|
|
||||||
|
|
||||||
|
#@toffee_test.testcase
|
||||||
|
#async def test_smoke(iprefetchpipe_env: IPrefetchPipeEnv):
|
||||||
|
# await iprefetchpipe_env.agent.set_s1_flush()
|
||||||
|
|
||||||
|
|
||||||
@toffee_test.testcase
|
@toffee_test.testcase
|
||||||
async def test_receive_prefetch(iprefetchpipe_env: IPrefetchPipeEnv):
|
async def test_receive_prefetch(iprefetchpipe_env: IPrefetchPipeEnv):
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,7 @@ def check_prefetch_is_soft_prefetch(dut: DUTIPrefetchPipe) -> bool:
|
||||||
return dut.IPrefetchPipe_s1_isSoftPrefetch.value == dut.io_req_bits_isSoftPrefetch.value
|
return dut.IPrefetchPipe_s1_isSoftPrefetch.value == dut.io_req_bits_isSoftPrefetch.value
|
||||||
|
|
||||||
def check_prefetch_double_line(dut: DUTIPrefetchPipe) -> bool:
|
def check_prefetch_double_line(dut: DUTIPrefetchPipe) -> bool:
|
||||||
if dut.io_req_bits_startAddr.value:
|
return dut.IPrefetchPipe_s1_doubleline.value == int((bin(dut.io_req_bits_startAddr.value)[2:])[-6])
|
||||||
return dut.IPrefetchPipe_s1_doubleline.value == int((bin(dut.io_req_bits_startAddr.value)[2:])[-6])
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def check_prefetch_ftq_idx_flag(dut: DUTIPrefetchPipe) -> bool:
|
def check_prefetch_ftq_idx_flag(dut: DUTIPrefetchPipe) -> bool:
|
||||||
return dut.IPrefetchPipe_s1_req_ftqIdx_flag.value == dut.io_req_bits_ftqIdx_flag.value
|
return dut.IPrefetchPipe_s1_req_ftqIdx_flag.value == dut.io_req_bits_ftqIdx_flag.value
|
||||||
|
|
|
||||||
|
|
@ -8,17 +8,25 @@ class ICacheMainPipeAgent(Agent):
|
||||||
bundle.set_all(0)
|
bundle.set_all(0)
|
||||||
self.bundle = bundle
|
self.bundle = bundle
|
||||||
|
|
||||||
async def flush_s0_fire(self):
|
async def set_flush(self):
|
||||||
|
|
||||||
# set s0_fire
|
print(
|
||||||
self.bundle.io._dataArray._toIData._3._ready.value = 1
|
f"\nBefore setting: \n \
|
||||||
self.bundle.io._wayLookupRead._valid.value = 1
|
s2_fire is: {self.bundle.ICacheMainPipe_s2._fire.value}\n \
|
||||||
self.bundle.io._fetch._req._valid.value = 1
|
_toMSHRArbiter_io_in_0_valid is: {self.bundle.ICacheMainPipe__toMSHRArbiter_io_in._0._valid_T._4.value}\n \
|
||||||
await self.bundle.step()
|
_toMSHRArbiter_io_in_1_valid is: {self.bundle.ICacheMainPipe__toMSHRArbiter_io_in._1._valid_T._4.value}\n \
|
||||||
|
s2_valid is: {self.bundle.ICacheMainPipe_s2._valid.value}\n \
|
||||||
print( f"\nBefore setting: s0_fire is: ",self.bundle.ICacheMainPipe._s0_fire.value)
|
"
|
||||||
|
)
|
||||||
|
|
||||||
self.bundle.io._flush.value = 1
|
self.bundle.io._flush.value = 1
|
||||||
await self.bundle.step()
|
await self.bundle.step()
|
||||||
|
|
||||||
print( f"After setting: s0_fire is: ",self.bundle.ICacheMainPipe._s0_fire.value)
|
print(
|
||||||
|
f"After setting: \n \
|
||||||
|
s2_fire is: {self.bundle.ICacheMainPipe_s2._fire.value}\n \
|
||||||
|
_toMSHRArbiter_io_in_0_valid is: {self.bundle.ICacheMainPipe__toMSHRArbiter_io_in._0._valid_T._4.value}\n \
|
||||||
|
_toMSHRArbiter_io_in_1_valid is: {self.bundle.ICacheMainPipe__toMSHRArbiter_io_in._1._valid_T._4.value}\n \
|
||||||
|
s2_valid is: {self.bundle.ICacheMainPipe_s2._valid.value}\n \
|
||||||
|
"
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,231 +1,282 @@
|
||||||
from toffee import Bundle, Signals, Signal
|
from toffee import Bundle, Signals, Signal
|
||||||
|
|
||||||
|
|
||||||
class _0Bundle(Bundle):
|
class _0Bundle(Bundle):
|
||||||
_fire, _valid = Signals(2)
|
_4 = Signal()
|
||||||
|
|
||||||
|
|
||||||
class _1Bundle(Bundle):
|
class _1Bundle(Bundle):
|
||||||
_s2 = _0Bundle.from_prefix("_s2")
|
_valid_T = _0Bundle.from_prefix("_valid_T")
|
||||||
_s0_fire = Signal()
|
|
||||||
|
|
||||||
class _2Bundle(Bundle):
|
class _2Bundle(Bundle):
|
||||||
_4 = Signal()
|
_0 = _1Bundle.from_prefix("_0")
|
||||||
|
_1 = _1Bundle.from_prefix("_1")
|
||||||
|
|
||||||
|
|
||||||
class _3Bundle(Bundle):
|
class _3Bundle(Bundle):
|
||||||
_valid_T = _2Bundle.from_prefix("_valid_T")
|
_fire, _valid = Signals(2)
|
||||||
|
|
||||||
|
|
||||||
class _4Bundle(Bundle):
|
class _4Bundle(Bundle):
|
||||||
_1 = _3Bundle.from_prefix("_1")
|
_6, _7, _3, _5, _4, _1, _2, _0 = Signals(8)
|
||||||
_0 = _3Bundle.from_prefix("_0")
|
|
||||||
|
|
||||||
class _5Bundle(Bundle):
|
class _5Bundle(Bundle):
|
||||||
_1, _7, _3, _4, _6, _2, _5, _0 = Signals(8)
|
_datas = _4Bundle.from_prefix("_datas")
|
||||||
|
_codes = _4Bundle.from_prefix("_codes")
|
||||||
|
|
||||||
|
|
||||||
class _6Bundle(Bundle):
|
class _6Bundle(Bundle):
|
||||||
_datas = _5Bundle.from_prefix("_datas")
|
_1, _0 = Signals(2)
|
||||||
_codes = _5Bundle.from_prefix("_codes")
|
|
||||||
|
|
||||||
class _7Bundle(Bundle):
|
class _7Bundle(Bundle):
|
||||||
_1, _0 = Signals(2)
|
_1, _0, _2, _3 = Signals(4)
|
||||||
|
|
||||||
|
|
||||||
class _8Bundle(Bundle):
|
class _8Bundle(Bundle):
|
||||||
_1, _2, _3, _0 = Signals(4)
|
_1 = _7Bundle.from_prefix("_1")
|
||||||
|
_0 = _7Bundle.from_prefix("_0")
|
||||||
|
|
||||||
|
|
||||||
class _9Bundle(Bundle):
|
class _9Bundle(Bundle):
|
||||||
_0 = _8Bundle.from_prefix("_0")
|
_waymask = _8Bundle.from_prefix("_waymask")
|
||||||
_1 = _8Bundle.from_prefix("_1")
|
_vSetIdx = _6Bundle.from_prefix("_vSetIdx")
|
||||||
|
_blkOffset = Signal()
|
||||||
|
|
||||||
|
|
||||||
class _10Bundle(Bundle):
|
class _10Bundle(Bundle):
|
||||||
_waymask = _9Bundle.from_prefix("_waymask")
|
_bits = _9Bundle.from_prefix("_bits")
|
||||||
_vSetIdx = _7Bundle.from_prefix("_vSetIdx")
|
_valid = Signal()
|
||||||
_blkOffset = Signal()
|
|
||||||
|
|
||||||
class _11Bundle(Bundle):
|
class _11Bundle(Bundle):
|
||||||
_bits = _10Bundle.from_prefix("_bits")
|
_bits_vSetIdx = _6Bundle.from_prefix("_bits_vSetIdx")
|
||||||
_valid = Signal()
|
_valid = Signal()
|
||||||
|
|
||||||
|
|
||||||
class _12Bundle(Bundle):
|
class _12Bundle(Bundle):
|
||||||
_bits_vSetIdx = _7Bundle.from_prefix("_bits_vSetIdx")
|
_bits_vSetIdx = _6Bundle.from_prefix("_bits_vSetIdx")
|
||||||
_valid = Signal()
|
_ready, _valid = Signals(2)
|
||||||
|
|
||||||
|
|
||||||
class _13Bundle(Bundle):
|
class _13Bundle(Bundle):
|
||||||
_bits_vSetIdx = _7Bundle.from_prefix("_bits_vSetIdx")
|
_3 = _12Bundle.from_prefix("_3")
|
||||||
_valid, _ready = Signals(2)
|
_1 = _11Bundle.from_prefix("_1")
|
||||||
|
_2 = _11Bundle.from_prefix("_2")
|
||||||
|
_0 = _10Bundle.from_prefix("_0")
|
||||||
|
|
||||||
|
|
||||||
class _14Bundle(Bundle):
|
class _14Bundle(Bundle):
|
||||||
_3 = _13Bundle.from_prefix("_3")
|
_fromIData = _5Bundle.from_prefix("_fromIData")
|
||||||
_1 = _12Bundle.from_prefix("_1")
|
_toIData = _13Bundle.from_prefix("_toIData")
|
||||||
_2 = _12Bundle.from_prefix("_2")
|
|
||||||
_0 = _11Bundle.from_prefix("_0")
|
|
||||||
|
|
||||||
class _15Bundle(Bundle):
|
class _15Bundle(Bundle):
|
||||||
_toIData = _14Bundle.from_prefix("_toIData")
|
_report_to_beu, _paddr = Signals(2)
|
||||||
_fromIData = _6Bundle.from_prefix("_fromIData")
|
|
||||||
|
|
||||||
class _16Bundle(Bundle):
|
class _16Bundle(Bundle):
|
||||||
_paddr, _report_to_beu = Signals(2)
|
_bits = _15Bundle.from_prefix("_bits")
|
||||||
|
_valid = Signal()
|
||||||
|
|
||||||
|
|
||||||
class _17Bundle(Bundle):
|
class _17Bundle(Bundle):
|
||||||
_bits = _16Bundle.from_prefix("_bits")
|
_0 = _16Bundle.from_prefix("_0")
|
||||||
_valid = Signal()
|
_1 = _16Bundle.from_prefix("_1")
|
||||||
|
|
||||||
|
|
||||||
class _18Bundle(Bundle):
|
class _18Bundle(Bundle):
|
||||||
_0 = _17Bundle.from_prefix("_0")
|
_startAddr, _nextlineStart = Signals(2)
|
||||||
_1 = _17Bundle.from_prefix("_1")
|
|
||||||
|
|
||||||
class _19Bundle(Bundle):
|
class _19Bundle(Bundle):
|
||||||
_nextlineStart, _startAddr = Signals(2)
|
_1 = _18Bundle.from_prefix("_1")
|
||||||
|
_3 = _18Bundle.from_prefix("_3")
|
||||||
|
_0 = _18Bundle.from_prefix("_0")
|
||||||
|
_4 = _18Bundle.from_prefix("_4")
|
||||||
|
_2 = _18Bundle.from_prefix("_2")
|
||||||
|
|
||||||
|
|
||||||
class _20Bundle(Bundle):
|
class _20Bundle(Bundle):
|
||||||
_0 = _19Bundle.from_prefix("_0")
|
_3, _4, _1, _2, _0 = Signals(5)
|
||||||
_1 = _19Bundle.from_prefix("_1")
|
|
||||||
_4 = _19Bundle.from_prefix("_4")
|
|
||||||
_2 = _19Bundle.from_prefix("_2")
|
|
||||||
_3 = _19Bundle.from_prefix("_3")
|
|
||||||
|
|
||||||
class _21Bundle(Bundle):
|
class _21Bundle(Bundle):
|
||||||
_1, _3, _4, _2, _0 = Signals(5)
|
_readValid = _20Bundle.from_prefix("_readValid")
|
||||||
|
_pcMemRead = _19Bundle.from_prefix("_pcMemRead")
|
||||||
|
_backendException = Signal()
|
||||||
|
|
||||||
|
|
||||||
class _22Bundle(Bundle):
|
class _22Bundle(Bundle):
|
||||||
_pcMemRead = _20Bundle.from_prefix("_pcMemRead")
|
_bits = _21Bundle.from_prefix("_bits")
|
||||||
_readValid = _21Bundle.from_prefix("_readValid")
|
_ready, _valid = Signals(2)
|
||||||
_backendException = Signal()
|
|
||||||
|
|
||||||
class _23Bundle(Bundle):
|
class _23Bundle(Bundle):
|
||||||
_bits = _22Bundle.from_prefix("_bits")
|
_0 = Signal()
|
||||||
_valid, _ready = Signals(2)
|
|
||||||
|
|
||||||
class _24Bundle(Bundle):
|
class _24Bundle(Bundle):
|
||||||
_0 = Signal()
|
_exception = _6Bundle.from_prefix("_exception")
|
||||||
|
_itlb_pbmt = _6Bundle.from_prefix("_itlb_pbmt")
|
||||||
|
_vaddr = _6Bundle.from_prefix("_vaddr")
|
||||||
|
_pmp_mmio = _6Bundle.from_prefix("_pmp_mmio")
|
||||||
|
_paddr = _23Bundle.from_prefix("_paddr")
|
||||||
|
_data, _doubleline, _gpaddr, _backendException, _isForVSnonLeafPTE = Signals(5)
|
||||||
|
|
||||||
|
|
||||||
class _25Bundle(Bundle):
|
class _25Bundle(Bundle):
|
||||||
_vaddr = _7Bundle.from_prefix("_vaddr")
|
_bits = _24Bundle.from_prefix("_bits")
|
||||||
_itlb_pbmt = _7Bundle.from_prefix("_itlb_pbmt")
|
_valid = Signal()
|
||||||
_exception = _7Bundle.from_prefix("_exception")
|
|
||||||
_pmp_mmio = _7Bundle.from_prefix("_pmp_mmio")
|
|
||||||
_paddr = _24Bundle.from_prefix("_paddr")
|
|
||||||
_data, _doubleline, _isForVSnonLeafPTE, _gpaddr, _backendException = Signals(5)
|
|
||||||
|
|
||||||
class _26Bundle(Bundle):
|
class _26Bundle(Bundle):
|
||||||
_bits = _25Bundle.from_prefix("_bits")
|
_resp = _25Bundle.from_prefix("_resp")
|
||||||
_valid = Signal()
|
_req = _22Bundle.from_prefix("_req")
|
||||||
|
_topdownIcacheMiss, _topdownItlbMiss = Signals(2)
|
||||||
|
|
||||||
|
|
||||||
class _27Bundle(Bundle):
|
class _27Bundle(Bundle):
|
||||||
_resp = _26Bundle.from_prefix("_resp")
|
_virIdx, _waymask = Signals(2)
|
||||||
_req = _23Bundle.from_prefix("_req")
|
|
||||||
_topdownIcacheMiss, _topdownItlbMiss = Signals(2)
|
|
||||||
|
|
||||||
class _28Bundle(Bundle):
|
class _28Bundle(Bundle):
|
||||||
_waymask, _virIdx = Signals(2)
|
_bits = _27Bundle.from_prefix("_bits")
|
||||||
|
_valid = Signal()
|
||||||
|
|
||||||
|
|
||||||
class _29Bundle(Bundle):
|
class _29Bundle(Bundle):
|
||||||
_bits = _28Bundle.from_prefix("_bits")
|
_0 = _28Bundle.from_prefix("_0")
|
||||||
_valid = Signal()
|
_1 = _28Bundle.from_prefix("_1")
|
||||||
|
|
||||||
|
|
||||||
class _30Bundle(Bundle):
|
class _30Bundle(Bundle):
|
||||||
_1 = _29Bundle.from_prefix("_1")
|
_blkPaddr, _vSetIdx = Signals(2)
|
||||||
_0 = _29Bundle.from_prefix("_0")
|
|
||||||
|
|
||||||
class _31Bundle(Bundle):
|
class _31Bundle(Bundle):
|
||||||
_blkPaddr, _vSetIdx = Signals(2)
|
_bits = _30Bundle.from_prefix("_bits")
|
||||||
|
_valid, _ready = Signals(2)
|
||||||
|
|
||||||
|
|
||||||
class _32Bundle(Bundle):
|
class _32Bundle(Bundle):
|
||||||
_bits = _31Bundle.from_prefix("_bits")
|
_corrupt, _blkPaddr, _vSetIdx, _data = Signals(4)
|
||||||
_valid, _ready = Signals(2)
|
|
||||||
|
|
||||||
class _33Bundle(Bundle):
|
class _33Bundle(Bundle):
|
||||||
_data, _blkPaddr, _vSetIdx, _corrupt = Signals(4)
|
_bits = _32Bundle.from_prefix("_bits")
|
||||||
|
_valid = Signal()
|
||||||
|
|
||||||
|
|
||||||
class _34Bundle(Bundle):
|
class _34Bundle(Bundle):
|
||||||
_bits = _33Bundle.from_prefix("_bits")
|
_resp = _33Bundle.from_prefix("_resp")
|
||||||
_valid = Signal()
|
_req = _31Bundle.from_prefix("_req")
|
||||||
|
|
||||||
|
|
||||||
class _35Bundle(Bundle):
|
class _35Bundle(Bundle):
|
||||||
_resp = _34Bundle.from_prefix("_resp")
|
_1 = Signal()
|
||||||
_req = _32Bundle.from_prefix("_req")
|
|
||||||
|
|
||||||
class _36Bundle(Bundle):
|
class _36Bundle(Bundle):
|
||||||
_1 = Signal()
|
_miss = _35Bundle.from_prefix("_miss")
|
||||||
|
_hit = _35Bundle.from_prefix("_hit")
|
||||||
|
_except = _35Bundle.from_prefix("_except")
|
||||||
|
|
||||||
|
|
||||||
class _37Bundle(Bundle):
|
class _37Bundle(Bundle):
|
||||||
_hit = _36Bundle.from_prefix("_hit")
|
_0 = _36Bundle.from_prefix("_0")
|
||||||
_except = _36Bundle.from_prefix("_except")
|
|
||||||
_miss = _36Bundle.from_prefix("_miss")
|
|
||||||
|
|
||||||
class _38Bundle(Bundle):
|
class _38Bundle(Bundle):
|
||||||
_0 = _37Bundle.from_prefix("_0")
|
_hit, _miss = Signals(2)
|
||||||
|
|
||||||
|
|
||||||
class _39Bundle(Bundle):
|
class _39Bundle(Bundle):
|
||||||
_miss, _hit = Signals(2)
|
_0 = _38Bundle.from_prefix("_0")
|
||||||
|
|
||||||
|
|
||||||
class _40Bundle(Bundle):
|
class _40Bundle(Bundle):
|
||||||
_0 = _39Bundle.from_prefix("_0")
|
_except = _23Bundle.from_prefix("_except")
|
||||||
|
_miss = _37Bundle.from_prefix("_miss")
|
||||||
|
_bank_hit = _6Bundle.from_prefix("_bank_hit")
|
||||||
|
_only = _39Bundle.from_prefix("_only")
|
||||||
|
_hit = Signal()
|
||||||
|
|
||||||
|
|
||||||
class _41Bundle(Bundle):
|
class _41Bundle(Bundle):
|
||||||
_bank_hit = _7Bundle.from_prefix("_bank_hit")
|
_mmio, _instr = Signals(2)
|
||||||
_miss = _38Bundle.from_prefix("_miss")
|
|
||||||
_except = _24Bundle.from_prefix("_except")
|
|
||||||
_only = _40Bundle.from_prefix("_only")
|
|
||||||
_hit = Signal()
|
|
||||||
|
|
||||||
class _42Bundle(Bundle):
|
class _42Bundle(Bundle):
|
||||||
_instr, _mmio = Signals(2)
|
_resp = _41Bundle.from_prefix("_resp")
|
||||||
|
_req_bits_addr = Signal()
|
||||||
|
|
||||||
|
|
||||||
class _43Bundle(Bundle):
|
class _43Bundle(Bundle):
|
||||||
_resp = _42Bundle.from_prefix("_resp")
|
_0 = _42Bundle.from_prefix("_0")
|
||||||
_req_bits_addr = Signal()
|
_1 = _42Bundle.from_prefix("_1")
|
||||||
|
|
||||||
|
|
||||||
class _44Bundle(Bundle):
|
class _44Bundle(Bundle):
|
||||||
_1 = _43Bundle.from_prefix("_1")
|
_way, _vSetIdx = Signals(2)
|
||||||
_0 = _43Bundle.from_prefix("_0")
|
|
||||||
|
|
||||||
class _45Bundle(Bundle):
|
class _45Bundle(Bundle):
|
||||||
_way, _vSetIdx = Signals(2)
|
_bits = _44Bundle.from_prefix("_bits")
|
||||||
|
_valid = Signal()
|
||||||
|
|
||||||
|
|
||||||
class _46Bundle(Bundle):
|
class _46Bundle(Bundle):
|
||||||
_bits = _45Bundle.from_prefix("_bits")
|
_0 = _45Bundle.from_prefix("_0")
|
||||||
_valid = Signal()
|
_1 = _45Bundle.from_prefix("_1")
|
||||||
|
|
||||||
|
|
||||||
class _47Bundle(Bundle):
|
class _47Bundle(Bundle):
|
||||||
_0 = _46Bundle.from_prefix("_0")
|
_pbmt = _6Bundle.from_prefix("_pbmt")
|
||||||
_1 = _46Bundle.from_prefix("_1")
|
_exception = _6Bundle.from_prefix("_exception")
|
||||||
|
|
||||||
|
|
||||||
class _48Bundle(Bundle):
|
class _48Bundle(Bundle):
|
||||||
_pbmt = _7Bundle.from_prefix("_pbmt")
|
_waymask = _6Bundle.from_prefix("_waymask")
|
||||||
_exception = _7Bundle.from_prefix("_exception")
|
_ptag = _6Bundle.from_prefix("_ptag")
|
||||||
|
_vSetIdx = _6Bundle.from_prefix("_vSetIdx")
|
||||||
|
_meta_codes = _6Bundle.from_prefix("_meta_codes")
|
||||||
|
_itlb = _47Bundle.from_prefix("_itlb")
|
||||||
|
|
||||||
|
|
||||||
class _49Bundle(Bundle):
|
class _49Bundle(Bundle):
|
||||||
_ptag = _7Bundle.from_prefix("_ptag")
|
_gpaddr, _isForVSnonLeafPTE = Signals(2)
|
||||||
_meta_codes = _7Bundle.from_prefix("_meta_codes")
|
|
||||||
_waymask = _7Bundle.from_prefix("_waymask")
|
|
||||||
_vSetIdx = _7Bundle.from_prefix("_vSetIdx")
|
|
||||||
_itlb = _48Bundle.from_prefix("_itlb")
|
|
||||||
|
|
||||||
class _50Bundle(Bundle):
|
class _50Bundle(Bundle):
|
||||||
_isForVSnonLeafPTE, _gpaddr = Signals(2)
|
_entry = _48Bundle.from_prefix("_entry")
|
||||||
|
_gpf = _49Bundle.from_prefix("_gpf")
|
||||||
|
|
||||||
|
|
||||||
class _51Bundle(Bundle):
|
class _51Bundle(Bundle):
|
||||||
_entry = _49Bundle.from_prefix("_entry")
|
_bits = _50Bundle.from_prefix("_bits")
|
||||||
_gpf = _50Bundle.from_prefix("_gpf")
|
_ready, _valid = Signals(2)
|
||||||
|
|
||||||
|
|
||||||
class _52Bundle(Bundle):
|
class _52Bundle(Bundle):
|
||||||
_bits = _51Bundle.from_prefix("_bits")
|
_dataArray = _14Bundle.from_prefix("_dataArray")
|
||||||
_valid, _ready = Signals(2)
|
_pmp = _43Bundle.from_prefix("_pmp")
|
||||||
|
_mshr = _34Bundle.from_prefix("_mshr")
|
||||||
|
_wayLookupRead = _51Bundle.from_prefix("_wayLookupRead")
|
||||||
|
_perfInfo = _40Bundle.from_prefix("_perfInfo")
|
||||||
|
_errors = _17Bundle.from_prefix("_errors")
|
||||||
|
_fetch = _26Bundle.from_prefix("_fetch")
|
||||||
|
_metaArrayFlush = _29Bundle.from_prefix("_metaArrayFlush")
|
||||||
|
_touch = _46Bundle.from_prefix("_touch")
|
||||||
|
_flush, _respStall, _ecc_enable, _hartId = Signals(4)
|
||||||
|
|
||||||
class _53Bundle(Bundle):
|
|
||||||
_perfInfo = _41Bundle.from_prefix("_perfInfo")
|
|
||||||
_pmp = _44Bundle.from_prefix("_pmp")
|
|
||||||
_errors = _18Bundle.from_prefix("_errors")
|
|
||||||
_metaArrayFlush = _30Bundle.from_prefix("_metaArrayFlush")
|
|
||||||
_wayLookupRead = _52Bundle.from_prefix("_wayLookupRead")
|
|
||||||
_dataArray = _15Bundle.from_prefix("_dataArray")
|
|
||||||
_mshr = _35Bundle.from_prefix("_mshr")
|
|
||||||
_fetch = _27Bundle.from_prefix("_fetch")
|
|
||||||
_touch = _47Bundle.from_prefix("_touch")
|
|
||||||
_hartId, _flush, _ecc_enable, _respStall = Signals(4)
|
|
||||||
|
|
||||||
class ICacheMainPipeBundle(Bundle):
|
class ICacheMainPipeBundle(Bundle):
|
||||||
ICacheMainPipe = _1Bundle.from_prefix("ICacheMainPipe")
|
ICacheMainPipe_s2 = _3Bundle.from_prefix("ICacheMainPipe_s2")
|
||||||
ICacheMainPipe__toMSHRArbiter_io_in = _4Bundle.from_prefix("ICacheMainPipe__toMSHRArbiter_io_in")
|
io = _52Bundle.from_prefix("io")
|
||||||
io = _53Bundle.from_prefix("io")
|
ICacheMainPipe__toMSHRArbiter_io_in = _2Bundle.from_prefix(
|
||||||
reset, clock = Signals(2)
|
"ICacheMainPipe__toMSHRArbiter_io_in"
|
||||||
|
)
|
||||||
|
clock, reset = Signals(2)
|
||||||
|
|
|
||||||
|
|
@ -4,4 +4,4 @@ import toffee_test
|
||||||
|
|
||||||
@toffee_test.testcase
|
@toffee_test.testcase
|
||||||
async def test_smoke(icachemainpipe_env: ICacheMainPipeEnv):
|
async def test_smoke(icachemainpipe_env: ICacheMainPipeEnv):
|
||||||
await icachemainpipe_env.agent.flush_s0_fire()
|
await icachemainpipe_env.agent.set_flush()
|
||||||
|
|
@ -13,10 +13,6 @@ async def icachemainpipe_env(toffee_request: toffee_test.ToffeeRequest):
|
||||||
dut.InitClock("clock")
|
dut.InitClock("clock")
|
||||||
start_clock(dut)
|
start_clock(dut)
|
||||||
icachemainpipe_env = ICacheMainPipeEnv(dut)
|
icachemainpipe_env = ICacheMainPipeEnv(dut)
|
||||||
icachemainpipe_env.dut.reset.value = 1
|
|
||||||
icachemainpipe_env.dut.Step(10)
|
|
||||||
icachemainpipe_env.dut.reset.value = 0
|
|
||||||
icachemainpipe_env.dut.Step(10)
|
|
||||||
yield icachemainpipe_env
|
yield icachemainpipe_env
|
||||||
|
|
||||||
cur_loop = asyncio.get_event_loop()
|
cur_loop = asyncio.get_event_loop()
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,6 @@ async def icachemissunit_env(toffee_request: toffee_test.ToffeeRequest):
|
||||||
dut.InitClock("clock")
|
dut.InitClock("clock")
|
||||||
start_clock(dut)
|
start_clock(dut)
|
||||||
icachemissunit_env = ICacheMissUnitEnv(dut)
|
icachemissunit_env = ICacheMissUnitEnv(dut)
|
||||||
icachemissunit_env.dut.reset.value = 1
|
|
||||||
icachemissunit_env.dut.Step(10)
|
|
||||||
icachemissunit_env.dut.reset.value = 0
|
|
||||||
icachemissunit_env.dut.Step(10)
|
|
||||||
yield icachemissunit_env
|
yield icachemissunit_env
|
||||||
|
|
||||||
cur_loop = asyncio.get_event_loop()
|
cur_loop = asyncio.get_event_loop()
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,34 @@
|
||||||
from toffee import Agent
|
from toffee import Agent
|
||||||
from ..bundle import WayLookupBundle
|
from ..bundle import WayLookupBundle
|
||||||
|
|
||||||
|
|
||||||
|
class ReadBitsData:
|
||||||
|
|
||||||
|
WayLookup_readPtr_value_before_flush: int
|
||||||
|
WayLookup_readPtr_value_after_flush: int
|
||||||
|
WayLookup_readPtr_flag_before_flush: bool
|
||||||
|
WayLookup_readPtr_flag_after_flush: bool
|
||||||
|
WayLookup_writePtr_value_before_flush: int
|
||||||
|
WayLookup_writePtr_value_after_flush: int
|
||||||
|
WayLookup_writePtr_flag_before_flush: bool
|
||||||
|
WayLookup_writePtr_flag_after_flush: bool
|
||||||
|
flush: int
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return (
|
||||||
|
f"\n"
|
||||||
|
f"WayLookup_readPtr_value_before_flush: {self.WayLookup_readPtr_value_before_flush}\n"
|
||||||
|
f"WayLookup_readPtr_value_after_flush: {self.WayLookup_readPtr_value_after_flush}\n"
|
||||||
|
f"WayLookup_readPtr_flag_before_flush: {self.WayLookup_readPtr_flag_before_flush}\n"
|
||||||
|
f"WayLookup_readPtr_flag_after_flush: {self.WayLookup_readPtr_flag_after_flush}\n"
|
||||||
|
f"WayLookup_writePtr_value_before_flush: {self.WayLookup_writePtr_value_before_flush}\n"
|
||||||
|
f"WayLookup_writePtr_value_after_flush: {self.WayLookup_writePtr_value_after_flush}\n"
|
||||||
|
f"WayLookup_writePtr_flag_before_flush: {self.WayLookup_writePtr_flag_before_flush}\n"
|
||||||
|
f"WayLookup_writePtr_flag_after_flush: {self.WayLookup_writePtr_flag_after_flush}\n"
|
||||||
|
f"flush: {self.flush}\n"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class WayLookupAgent(Agent):
|
class WayLookupAgent(Agent):
|
||||||
|
|
||||||
def __init__(self, bundle: WayLookupBundle):
|
def __init__(self, bundle: WayLookupBundle):
|
||||||
|
|
@ -8,30 +36,38 @@ class WayLookupAgent(Agent):
|
||||||
bundle.set_all(0)
|
bundle.set_all(0)
|
||||||
self.bundle = bundle
|
self.bundle = bundle
|
||||||
|
|
||||||
async def flush_write_ptr(self):
|
async def flush(self) -> ReadBitsData:
|
||||||
|
|
||||||
# set io_write_fire,io.write.ready is already 1
|
ret = ReadBitsData()
|
||||||
self.bundle.io._write._valid.value = 1
|
|
||||||
await self.bundle.step()
|
ret.WayLookup_readPtr_value_before_flush = (
|
||||||
|
self.bundle.WayLookup._readPtr._value.value
|
||||||
# set write_ptr by writting entry
|
)
|
||||||
self.bundle.io._write._bits._entry._vSetIdx._0.value = 0
|
ret.WayLookup_readPtr_flag_before_flush = (
|
||||||
self.bundle.io._write._bits._entry._vSetIdx._1.value = 1
|
self.bundle.WayLookup._readPtr._flag.value
|
||||||
self.bundle.io._write._bits._entry._waymask._0.value = 0
|
)
|
||||||
self.bundle.io._write._bits._entry._waymask._1.value = 1
|
ret.WayLookup_writePtr_value_before_flush = (
|
||||||
self.bundle.io._write._bits._entry._ptag._0.value = 0
|
self.bundle.WayLookup._writePtr._value.value
|
||||||
self.bundle.io._write._bits._entry._ptag._1.value = 1
|
)
|
||||||
self.bundle.io._write._bits._entry._itlb._exception._0.value = 0
|
ret.WayLookup_writePtr_flag_before_flush = (
|
||||||
self.bundle.io._write._bits._entry._itlb._exception._1.value = 1
|
self.bundle.WayLookup._writePtr._flag.value
|
||||||
self.bundle.io._write._bits._entry._meta_codes._0.value = 0
|
)
|
||||||
self.bundle.io._write._bits._entry._meta_codes._1.value = 1
|
|
||||||
await self.bundle.step()
|
|
||||||
print("Before flush, write_ptr is: ", self.bundle.WayLookup._writePtr._value.value)
|
|
||||||
|
|
||||||
# flush
|
|
||||||
self.bundle.io._flush.value = 1
|
self.bundle.io._flush.value = 1
|
||||||
await self.bundle.step()
|
await self.bundle.step()
|
||||||
|
|
||||||
# print
|
ret.WayLookup_readPtr_value_after_flush = (
|
||||||
print("After flush, write_ptr is: ", self.bundle.WayLookup._writePtr._value.value)
|
self.bundle.WayLookup._readPtr._value.value
|
||||||
await self.bundle.step()
|
)
|
||||||
|
ret.WayLookup_readPtr_flag_after_flush = (
|
||||||
|
self.bundle.WayLookup._readPtr._flag.value
|
||||||
|
)
|
||||||
|
ret.WayLookup_writePtr_value_after_flush = (
|
||||||
|
self.bundle.WayLookup._writePtr._value.value
|
||||||
|
)
|
||||||
|
ret.WayLookup_writePtr_flag_after_flush = (
|
||||||
|
self.bundle.WayLookup._writePtr._flag.value
|
||||||
|
)
|
||||||
|
|
||||||
|
ret.flush = self.bundle.io._flush.value
|
||||||
|
return ret
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,6 @@ async def waylookup_env(toffee_request: toffee_test.ToffeeRequest):
|
||||||
dut.InitClock("clock")
|
dut.InitClock("clock")
|
||||||
start_clock(dut)
|
start_clock(dut)
|
||||||
waylookup_env = WayLookupEnv(dut)
|
waylookup_env = WayLookupEnv(dut)
|
||||||
waylookup_env.dut.reset.value = 1
|
|
||||||
waylookup_env.dut.Step(10)
|
|
||||||
waylookup_env.dut.reset.value = 0
|
|
||||||
waylookup_env.dut.Step(10)
|
|
||||||
yield waylookup_env
|
yield waylookup_env
|
||||||
|
|
||||||
cur_loop = asyncio.get_event_loop()
|
cur_loop = asyncio.get_event_loop()
|
||||||
|
|
|
||||||
|
|
@ -5,4 +5,5 @@ import toffee_test
|
||||||
|
|
||||||
@toffee_test.testcase
|
@toffee_test.testcase
|
||||||
async def test_smoke(waylookup_env: WayLookupEnv):
|
async def test_smoke(waylookup_env: WayLookupEnv):
|
||||||
await waylookup_env.agent.flush_write_ptr()
|
|
||||||
|
print(await waylookup_env.agent.flush())
|
||||||
|
|
|
||||||
|
|
@ -1,304 +1,248 @@
|
||||||
# **Translation Lookaside Buffer (TLB)**
|
# **Translation Lookaside Buffer (TLB)**
|
||||||
|
|
||||||
## 一、TLB IO 信号总表
|
## 一、TLB.sv 接口说明
|
||||||
|
|
||||||
### 1. 全局控制信号
|
### 基本控制信号
|
||||||
|
|
||||||
| 信号名 | 方向 | 位宽 | 描述 |
|
1. **`clock`**: 时钟信号,驱动 TLB 的时序逻辑。
|
||||||
|---------------|---------|------|-----------------------------|
|
2. **`reset`**: 复位信号,用于重置 TLB 的状态。
|
||||||
| clock | `input` | 1 | 时钟信号,驱动 TLB 的时序逻辑 |
|
|
||||||
| reset | `input` | 1 | 复位信号,用于重置 TLB 的状态 |
|
|
||||||
| io_hartId | `input` | 6 | 硬件线程ID |
|
|
||||||
|
|
||||||
### 2. SFENCE 指令接口信号
|
### 刷新(SFENCE)接口信号
|
||||||
|
|
||||||
| 信号名 | 方向 | 位宽 | 描述 |
|
这些信号与 TLB 的刷新操作相关,当页表被修改时,这些信号用于通知 TLB 刷新其内容。
|
||||||
|---------------------------------|---------|------|--------------------------------------|
|
|
||||||
| io_sfence_valid | `input` | 1 | SFENCE操作有效信号 |
|
|
||||||
| io_sfence_bits_rs1 | `input` | 1 | 指示是否使用寄存器rs1的值(地址) |
|
|
||||||
| io_sfence_bits_rs2 | `input` | 1 | 指示是否使用寄存器rs2的值(ASID) |
|
|
||||||
| io_sfence_bits_addr | `input` | 50 | SFENCE操作指定要刷新的虚拟地址,用于选择性刷新特定地址的 TLB 条目 |
|
|
||||||
| io_sfence_bits_id | `input` | 16 | SFENCE操作指定要刷新的ASID,用于选择性刷新特定地址空间的 TLB 条目 |
|
|
||||||
| io_sfence_bits_flushPipe | `input` | 1 | 指示当前 SFENCE 操作是否刷新流水线 |
|
|
||||||
| io_sfence_bits_hv | `input` | 1 | 是否在Hypervisor模式下执行SFENCE |
|
|
||||||
| io_sfence_bits_hg | `input` | 1 | 是否在Hypervisor guest模式下执行SFENCE |
|
|
||||||
|
|
||||||
### 3. CSR 寄存器输入
|
3. **`io_sfence_valid`**: 表示 SFENCE 操作的有效性。
|
||||||
|
4. **`io_sfence_bits_rs1`**: 表示 SFENCE 操作是否使用寄存器 rs1 的值。
|
||||||
|
5. **`io_sfence_bits_rs2`**: 表示 SFENCE 操作是否使用寄存器 rs2 的值。
|
||||||
|
6. **`io_sfence_bits_addr`**: SFENCE 操作指定的地址,用于选择性刷新特定地址的 TLB 条目。
|
||||||
|
7. **`io_sfence_bits_id`**: 标识符,用于区分不同的刷新操作。
|
||||||
|
8. **`io_sfence_bits_flushPipe`**: 请求刷新整个管道(Pipeline)。
|
||||||
|
9. **`io_sfence_bits_hv`**: 代表是否是 Hypervisor 模式下的 SFENCE 操作。
|
||||||
|
10. **`io_sfence_bits_hg`**: 代表是否是 Guest 模式下的 SFENCE 操作。
|
||||||
|
|
||||||
| 信号名 | 方向 | 位宽 | 描述 |
|
### 控制与状态寄存器(CSR)接口信号
|
||||||
|---------------------------------|---------|------|-----------------------------------|
|
|
||||||
| io_csr_satp_mode | `input` | 4 | SATP寄存器模式位 |
|
|
||||||
| io_csr_satp_asid | `input` | 16 | SATP寄存器ASID |
|
|
||||||
| io_csr_satp_ppn | `input` | 44 | SATP寄存器PPN |
|
|
||||||
| io_csr_satp_changed | `input` | 1 | SATP寄存器是否发生变化 |
|
|
||||||
| io_csr_vsatp_mode | `input` | 4 | VSATP寄存器模式位(虚拟化) |
|
|
||||||
| io_csr_vsatp_asid | `input` | 16 | VSATP寄存器ASID |
|
|
||||||
| io_csr_vsatp_ppn | `input` | 44 | VSATP寄存器PPN |
|
|
||||||
| io_csr_vsatp_changed | `input` | 1 | VSATP寄存器是否发生变化 |
|
|
||||||
| io_csr_hgatp_mode | `input` | 4 | HGATP寄存器模式位(虚拟化) |
|
|
||||||
| io_csr_hgatp_vmid | `input` | 16 | HGATP寄存器VMID |
|
|
||||||
| io_csr_hgatp_ppn | `input` | 44 | HGATP寄存器PPN |
|
|
||||||
| io_csr_hgatp_changed | `input` | 1 | HGATP寄存器是否发生变化 |
|
|
||||||
| io_csr_priv_virt | `input` | 1 | 虚拟化使能信号 |
|
|
||||||
| io_csr_priv_imode | `input` | 2 | 当前特权模式(00:U, 01:S, 11:M) |
|
|
||||||
|
|
||||||
### 4. 请求与响应接口(Requestor 0)
|
这些信号与 TLB 的控制与状态寄存器(CSR)配置相关。
|
||||||
|
|
||||||
| 信号名 | 方向 | 位宽 | 描述 |
|
11. **`io_csr_satp_mode`**: SATP 寄存器的模式字段(如裸模式、Sv32、Sv39 等)。
|
||||||
|--------------------------------------------|----------|------|--------------------------------|
|
12. **`io_csr_satp_asid`**: 当前 SATP 寄存器的 ASID(地址空间标识符)。
|
||||||
| io_requestor_0_req_valid | `input` | 1 | 请求0有效 |
|
13. **`io_csr_satp_changed`**: 指示 SATP 寄存器的值是否已更改。
|
||||||
| io_requestor_0_req_bits_vaddr | `input` | 50 | 请求0的虚拟地址 |
|
14. **`io_csr_vsatp_mode`**: VSATP 寄存器的模式字段。
|
||||||
| io_requestor_0_resp_bits_paddr_0 | `output` | 48 | 响应0的物理地址 |
|
15. **`io_csr_vsatp_asid`**: VSATP 寄存器的 ASID。
|
||||||
| io_requestor_0_resp_bits_gpaddr_0 | `output` | 64 | 响应0的虚拟化物理地址 |
|
16. **`io_csr_vsatp_changed`**: 指示 VSATP 寄存器的值是否已更改。
|
||||||
| io_requestor_0_resp_bits_pbmt_0 | `output` | 2 | 响应0的物理内存保护类型 |
|
17. **`io_csr_hgatp_mode`**: HGATP 寄存器的模式字段。
|
||||||
| io_requestor_0_resp_bits_miss | `output` | 1 | 响应0是否TLB缺失 |
|
18. **`io_csr_hgatp_vmid`**: HGATP 寄存器的 VMID(虚拟机标识符)。
|
||||||
| io_requestor_0_resp_bits_isForVSnonLeafPTE | `output` | 1 | 响应0是否为虚拟机非叶子PTE |
|
19. **`io_csr_hgatp_changed`**: 指示 HGATP 寄存器的值是否已更改。
|
||||||
| io_requestor_0_resp_bits_excp_0_gpf_instr | `output` | 1 | 指令0的虚拟化缺页异常 |
|
20. **`io_csr_priv_virt`**: 是否在虚拟模式下运行。
|
||||||
| io_requestor_0_resp_bits_excp_0_pf_instr | `output` | 1 | 指令0的缺页异常 |
|
21. **`io_csr_priv_imode`**: 指令模式的特权级(如用户态、内核态等)。
|
||||||
| io_requestor_0_resp_bits_excp_0_af_instr | `output` | 1 | 指令0的访问权限异常 |
|
|
||||||
|
|
||||||
### 5. 请求与响应接口(Requestor 1)
|
### 请求者(Requestor)接口信号
|
||||||
|
|
||||||
| 信号名 | 方向 | 位宽 | 描述 |
|
这些信号用于与处理器或其他模块之间的请求与响应操作。
|
||||||
|--------------------------------------------|----------|------|---------------------------------|
|
|
||||||
| io_requestor_1_req_valid | `input` | 1 | 请求1有效 |
|
|
||||||
| io_requestor_1_req_bits_vaddr | `input` | 50 | 请求1的虚拟地址 |
|
|
||||||
| io_requestor_1_resp_bits_paddr_0 | `output` | 48 | 响应1的物理地址 |
|
|
||||||
| io_requestor_1_resp_bits_gpaddr_0 | `output` | 64 | 响应1的虚拟化物理地址 |
|
|
||||||
| io_requestor_1_resp_bits_pbmt_0 | `output` | 2 | 响应1的物理内存保护类型 |
|
|
||||||
| io_requestor_1_resp_bits_miss | `output` | 1 | 响应1是否TLB缺失 |
|
|
||||||
| io_requestor_1_resp_bits_isForVSnonLeafPTE | `output` | 1 | 响应1是否为虚拟机非叶子PTE |
|
|
||||||
| io_requestor_1_resp_bits_excp_0_gpf_instr | `output` | 1 | 数据访问0的虚拟化缺页异常 |
|
|
||||||
| io_requestor_1_resp_bits_excp_0_pf_instr | `output` | 1 | 数据访问0的缺页异常 |
|
|
||||||
| io_requestor_1_resp_bits_excp_0_af_instr | `output` | 1 | 数据访问0的访问权限异常 |
|
|
||||||
|
|
||||||
### 6. 请求与响应接口(Requestor 2)
|
#### Requestor 0 信号
|
||||||
|
|
||||||
| 信号名 | 方向 | 位宽 | 描述 |
|
22. **`io_requestor_0_req_valid`**: 请求者 0 的请求有效信号。
|
||||||
|--------------------------------------------|----------|----|--------------------------------|
|
23. **`io_requestor_0_req_bits_vaddr`**: 请求者 0 的请求虚拟地址(vaddr)。
|
||||||
| io_requestor_2_req_ready | `output` | 1 | 请求2就绪信号 |
|
24. **`io_requestor_0_resp_bits_paddr_0`**: 请求者 0 的物理地址(paddr)响应信号。
|
||||||
| io_requestor_2_req_valid | `input` | 1 | 请求2有效 |
|
25. **`io_requestor_0_resp_bits_gpaddr_0`**: 请求者 0 的物理地址转换为 GPA(Guest Physical Address)的响应信号。
|
||||||
| io_requestor_2_req_bits_vaddr | `input` | 50 | 请求2的虚拟地址 |
|
26. **`io_requestor_0_resp_bits_miss`**: 请求者 0 请求的地址未命中的信号。
|
||||||
| io_requestor_2_resp_ready | `input` | 1 | 响应2就绪信号 |
|
27. **`io_requestor_0_resp_bits_excp_0_gpf_instr`**: 请求者 0 出现 General Protection Fault (GPF) 异常的信号。
|
||||||
| io_requestor_2_resp_valid | `output` | 1 | 响应2有效 |
|
28. **`io_requestor_0_resp_bits_excp_0_pf_instr`**: 请求者 0 出现 Page Fault (PF) 异常的信号。
|
||||||
| io_requestor_2_resp_bits_paddr_0 | `output` | 48 | 响应2的物理地址 |
|
29. **`io_requestor_0_resp_bits_excp_0_af_instr`**: 请求者 0 出现 Access Fault (AF) 异常的信号。
|
||||||
| io_requestor_2_resp_bits_gpaddr_0 | `output` | 64 | 响应2的虚拟化物理地址 |
|
|
||||||
| io_requestor_2_resp_bits_pbmt_0 | `output` | 2 | 响应2的物理内存保护类型 |
|
|
||||||
| io_requestor_2_resp_bits_miss | `output` | 1 | 响应2是否TLB缺失 |
|
|
||||||
| io_requestor_2_resp_bits_isForVSnonLeafPTE | `output` | 1 | 响应2是否为虚拟机非叶子PTE |
|
|
||||||
| io_requestor_2_resp_bits_excp_0_gpf_instr | `output` | 1 | PTW访问的虚拟化缺页异常 |
|
|
||||||
| io_requestor_2_resp_bits_excp_0_pf_instr | `output` | 1 | PTW访问的缺页异常 |
|
|
||||||
| io_requestor_2_resp_bits_excp_0_af_instr | `output` | 1 | PTW访问的访问权限异常 |
|
|
||||||
|
|
||||||
### 7. 流水线刷新信号(来自外部)
|
#### Requestor 1 信号
|
||||||
|
|
||||||
| 信号名 | 方向 | 位宽 | 描述 |
|
30. **`io_requestor_1_req_valid`**: 请求者 1 的请求有效信号。
|
||||||
|-----------------------|---------|------|---------------|
|
31. **`io_requestor_1_req_bits_vaddr`**: 请求者 1 的请求虚拟地址。
|
||||||
| io_flushPipe_0 | `input` | 1 | 刷新流水线 0 |
|
32. **`io_requestor_1_resp_bits_paddr_0`**: 请求者 1 的物理地址响应信号。
|
||||||
| io_flushPipe_1 | `input` | 1 | 刷新流水线 1 |
|
33. **`io_requestor_1_resp_bits_gpaddr_0`**: 请求者 1 的 GPA 响应信号。
|
||||||
| io_flushPipe_2 | `input` | 1 | 刷新流水线 2 |
|
34. **`io_requestor_1_resp_bits_miss`**: 请求者 1 的未命中信号。
|
||||||
|
35. **`io_requestor_1_resp_bits_excp_0_gpf_instr`**: 请求者 1 出现 GPF 异常的信号。
|
||||||
|
36. **`io_requestor_1_resp_bits_excp_0_pf_instr`**: 请求者 1 出现 PF 异常的信号。
|
||||||
|
37. **`io_requestor_1_resp_bits_excp_0_af_instr`**: 请求者 1 出现 AF 异常的信号。
|
||||||
|
|
||||||
### 8. PTW 请求接口(共3个通道)
|
#### Requestor 2 信号
|
||||||
|
|
||||||
| 信号名 | 方向 | 位宽 | 描述 |
|
38. **`io_requestor_2_req_ready`**: 请求者 2 的请求就绪信号。
|
||||||
|-----------------------------|----------|------|----------------------------------|
|
39. **`io_requestor_2_req_valid`**: 请求者 2 的请求有效信号。
|
||||||
| io_ptw_req_0_valid | `output` | 1 | PTW请求通道0有效 |
|
40. **`io_requestor_2_req_bits_vaddr`**: 请求者 2 的请求虚拟地址。
|
||||||
| io_ptw_req_0_bits_vpn | `output` | 38 | 请求的虚拟页号(VPN) |
|
41. **`io_requestor_2_resp_ready`**: 请求者 2 的响应就绪信号。
|
||||||
| io_ptw_req_0_bits_s2xlate | `output` | 2 | 二级转换类型指示 |
|
42. **`io_requestor_2_resp_valid`**: 请求者 2 的响应有效信号。
|
||||||
| io_ptw_req_0_bits_getGpa | `output` | 1 | 是否请求获得GPA |
|
43. **`io_requestor_2_resp_bits_paddr_0`**: 请求者 2 的物理地址响应信号。
|
||||||
| io_ptw_req_1_valid | `output` | 1 | PTW请求通道1有效 |
|
44. **`io_requestor_2_resp_bits_gpaddr_0`**: 请求者 2 的 GPA 响应信号。
|
||||||
| io_ptw_req_1_bits_vpn | `output` | 38 | 请求的虚拟页号(VPN) |
|
45. **`io_requestor_2_resp_bits_excp_0_gpf_instr`**: 请求者 2 出现 GPF 异常的信号。
|
||||||
| io_ptw_req_1_bits_s2xlate | `output` | 2 | 二级转换类型指示 |
|
46. **`io_requestor_2_resp_bits_excp_0_pf_instr`**: 请求者 2 出现 PF 异常的信号。
|
||||||
| io_ptw_req_1_bits_getGpa | `output` | 1 | 是否请求获得GPA |
|
47. **`io_requestor_2_resp_bits_excp_0_af_instr`**: 请求者 2 出现 AF 异常的信号。
|
||||||
| io_ptw_req_2_ready | `input` | 1 | PTW请求通道2就绪 |
|
|
||||||
| io_ptw_req_2_valid | `output` | 1 | PTW请求通道2有效 |
|
|
||||||
| io_ptw_req_2_bits_vpn | `output` | 38 | 请求的虚拟页号(VPN) |
|
|
||||||
| io_ptw_req_2_bits_s2xlate | `output` | 2 | 二级转换类型指示 |
|
|
||||||
| io_ptw_req_2_bits_getGpa | `output` | 1 | 是否请求获得GPA |
|
|
||||||
|
|
||||||
### 9. PTW 响应接口(共1个通道)
|
### 刷新管道(Flush Pipe)信号
|
||||||
|
|
||||||
| 信号名 | 方向 | 位宽 | 描述 |
|
这些信号用于通知 TLB 刷新请求。
|
||||||
|------------------------------------|---------|------|-----------------------------------|
|
|
||||||
| io_ptw_resp_valid | `input` | 1 | PTW响应有效 |
|
48. **`io_flushPipe_0`**: 刷新管道 0 的信号。
|
||||||
| io_ptw_resp_bits_s2xlate | `input` | 2 | 二级转换类型(回环) |
|
49. **`io_flushPipe_1`**: 刷新管道 1 的信号。
|
||||||
| **s1_entry 相关信号** | | | **第一级转换响应信息** |
|
50. **`io_flushPipe_2`**: 刷新管道 2 的信号。
|
||||||
| io_ptw_resp_bits_s1_entry_tag | `input` | 35 | 标签(VPN高位) |
|
|
||||||
| io_ptw_resp_bits_s1_entry_asid | `input` | 16 | ASID |
|
### 页表遍历(Page Table Walker, PTW)接口信号
|
||||||
| io_ptw_resp_bits_s1_entry_vmid | `input` | 14 | VMID |
|
|
||||||
| io_ptw_resp_bits_s1_entry_n | `input` | 1 | 非叶子节点标志 |
|
这些信号用于与页表遍历单元(PTW)的交互,处理 TLB 未命中的情况。
|
||||||
| io_ptw_resp_bits_s1_entry_pbmt | `input` | 2 | 物理内存保护类型 |
|
|
||||||
| io_ptw_resp_bits_s1_entry_perm_d | `input` | 1 | 脏位标志(D) |
|
#### PTW 请求信号
|
||||||
| io_ptw_resp_bits_s1_entry_perm_a | `input` | 1 | 访问位(A) |
|
|
||||||
| io_ptw_resp_bits_s1_entry_perm_g | `input` | 1 | 全局映射(G) |
|
51. **`io_ptw_req_0_valid`**: PTW 请求 0 有效信号。
|
||||||
| io_ptw_resp_bits_s1_entry_perm_u | `input` | 1 | 用户模式访问位(U) |
|
52. **`io_ptw_req_0_bits_vpn`**: PTW 请求 0 的虚拟页号(VPN)。
|
||||||
| io_ptw_resp_bits_s1_entry_perm_x | `input` | 1 | 执行位(X) |
|
53. **`io_ptw_req_0_bits_s2xlate`**: PTW 请求 0 的 S2 转换位。
|
||||||
| io_ptw_resp_bits_s1_entry_perm_w | `input` | 1 | 写位(W) |
|
54. **`io_ptw_req_0_bits_getGpa`**: PTW 请求 0 的获取 GPA 信号。
|
||||||
| io_ptw_resp_bits_s1_entry_perm_r | `input` | 1 | 读位(R) |
|
55. **`io_ptw_req_1_valid`**: PTW 请求 1 有效信号。
|
||||||
| io_ptw_resp_bits_s1_entry_level | `input` | 2 | 页表级(0-2) |
|
56. **`io_ptw_req_1_bits_vpn`**: PTW 请求 1 的虚拟页号。
|
||||||
| io_ptw_resp_bits_s1_entry_v | `input` | 1 | 页表项有效标志 |
|
57. **`io_ptw_req_1_bits_s2xlate`**: PTW 请求 1 的 S2 转换位。
|
||||||
| io_ptw_resp_bits_s1_entry_ppn | `input` | 41 | 物理页号(PPN) |
|
58. **`io_ptw_req_1_bits_getGpa`**: PTW 请求 1 的获取 GPA 信号。
|
||||||
| io_ptw_resp_bits_s1_addr_low | `input` | 3 | 虚拟地址低位(页内偏移高位) |
|
59. **`io_ptw_req_2_ready`**: PTW 请求 2 就绪信号。
|
||||||
| io_ptw_resp_bits_s1_ppn_low_[0-7] | `input` | 8×3 | PPN低位(8组) |
|
60. **`io_ptw_req_2_valid`**: PTW 请求 2 有效信号。
|
||||||
| io_ptw_resp_bits_s1_valididx_[0-7] | `input` | 8×1 | 页表项索引有效性(位图) |
|
61. **`io_ptw_req_2_bits_vpn`**: PTW 请求 2 的虚拟页号。
|
||||||
| io_ptw_resp_bits_s1_pteidx_[0-7] | `input` | 8×1 | 真实PTE索引(位图) |
|
62. **`io_ptw_req_2_bits_s2xlate`**: PTW 请求 2 的 S2 转换位。
|
||||||
| io_ptw_resp_bits_s1_pf | `input` | 1 | 第一级转换缺页错误标志 |
|
63. **`io_ptw_req_2_bits_getGpa`**: PTW 请求 2 的获取 GPA 信号。
|
||||||
| io_ptw_resp_bits_s1_af | `input` | 1 | 第一级转换访问错误标志 |
|
|
||||||
| **s2_entry 相关信号** | | | **第二级转换响应信息** |
|
#### PTW 响应信号
|
||||||
| io_ptw_resp_bits_s2_entry_tag | `input` | 38 | 标签(GPA高位) |
|
|
||||||
| io_ptw_resp_bits_s2_entry_vmid | `input` | 14 | VMID |
|
64. **`io_ptw_resp_valid`**: PTW 响应有效信号。
|
||||||
| io_ptw_resp_bits_s2_entry_n | `input` | 1 | 非叶子节点标志 |
|
65. **`io_ptw_resp_bits_s2xlate`**: PTW 响应的 S2 转换位。
|
||||||
| io_ptw_resp_bits_s2_entry_pbmt | `input` | 2 | 物理内存保护类型 |
|
66. **`io_ptw_resp_bits_s1_entry_tag`**: PTW 响应的第一级页表条目标签。
|
||||||
| io_ptw_resp_bits_s2_entry_ppn | `input` | 38 | 物理页号(PPN) |
|
67. **`io_ptw_resp_bits_s1_entry_asid`**: PTW 响应的第一级页表条目 ASID。
|
||||||
| io_ptw_resp_bits_s2_entry_perm_d | `input` | 1 | 脏位标志(D) |
|
68. **`io_ptw_resp_bits_s1_entry_vmid`**: PTW 响应的第一级页表条目 VMID。
|
||||||
| io_ptw_resp_bits_s2_entry_perm_a | `input` | 1 | 访问位(A) |
|
69. **`io_ptw_resp_bits_s1_entry_perm_d`**: PTW 响应的第一级页表条目可写位。
|
||||||
| io_ptw_resp_bits_s2_entry_perm_g | `input` | 1 | 全局映射(G) |
|
70. **`io_ptw_resp_bits_s1_entry_perm_a`**: PTW 响应的第一级页表条目已访问位。
|
||||||
| io_ptw_resp_bits_s2_entry_perm_u | `input` | 1 | 用户模式访问位(U) |
|
71. **`io_ptw_resp_bits_s1_entry_perm_g`**: PTW 响应的第一级页表条目全局位。
|
||||||
| io_ptw_resp_bits_s2_entry_perm_x | `input` | 1 | 执行位(X) |
|
72. **`io_ptw_resp_bits_s1_entry_perm_u`**: PTW 响应的第一级页表条目用户模式位。
|
||||||
| io_ptw_resp_bits_s2_entry_perm_w | `input` | 1 | 写位(W) |
|
73. **`io_ptw_resp_bits_s1_entry_perm_x`**: PTW 响应的第一级页表条目可执行位。
|
||||||
| io_ptw_resp_bits_s2_entry_perm_r | `input` | 1 | 读位(R) |
|
74. **`io_ptw_resp_bits_s1_entry_perm_w`**: PTW 响应的第一级页表条目可写位。
|
||||||
| io_ptw_resp_bits_s2_entry_level | `input` | 2 | 页表级(0-2) |
|
75. **`io_ptw_resp_bits_s1_entry_perm_r`**: PTW 响应的第一级页表条目可读位。
|
||||||
| io_ptw_resp_bits_s2_gpf | `input` | 1 | 第二级转换非法权限错误标志 |
|
76. **`io_ptw_resp_bits_s1_entry_level`**: PTW 响应的第一级页表条目级别。
|
||||||
| io_ptw_resp_bits_s2_gaf | `input` | 1 | 第二级转换访问错误标志 |
|
77. **`io_ptw_resp_bits_s1_entry_ppn`**: PTW 响应的第一级页表条目物理页号(PPN)。
|
||||||
| io_ptw_resp_bits_getGpa | `input` | 1 | 响应中是否包含GPA |
|
78. **`io_ptw_resp_bits_s1_addr_low`**: PTW 响应的第一级页表条目地址低位。
|
||||||
|
79. **`io_ptw_resp_bits_s1_ppn_low_*`**: PTW 响应的第一级页表条目 PPN 低位。
|
||||||
|
80. **`io_ptw_resp_bits_s1_valididx_*`**: PTW 响应的第一级页表条目有效索引。
|
||||||
|
81. **`io_ptw_resp_bits_s1_pteidx_*`**: PTW 响应的第一级页表条目 PTE 索引。
|
||||||
|
82. **`io_ptw_resp_bits_s1_pf`**: PTW 响应的第一级页表条目页错误信号。
|
||||||
|
83. **`io_ptw_resp_bits_s1_af`**: PTW 响应的第一级页表条目访问错误信号。
|
||||||
|
84. **`io_ptw_resp_bits_s2_entry_tag`**: PTW 响应的第二级页表条目标签。
|
||||||
|
85. **`io_ptw_resp_bits_s2_entry_vmid`**: PTW 响应的第二级页表条目 VMID。
|
||||||
|
86. **`io_ptw_resp_bits_s2_entry_ppn`**: PTW 响应的第二级页表条目 PPN。
|
||||||
|
87. **`io_ptw_resp_bits_s2_entry_perm_*`**: PTW 响应的第二级页表条目的权限位。
|
||||||
|
88. **`io_ptw_resp_bits_s2_entry_level`**: PTW 响应的第二级页表条目级别。
|
||||||
|
89. **`io_ptw_resp_bits_s2_gpf`**: PTW 响应的第二级页表条目 GPF 信号。
|
||||||
|
90. **`io_ptw_resp_bits_s2_gaf`**: PTW 响应的第二级页表条目 GAF 信号。
|
||||||
|
91. **`io_ptw_resp_bits_getGpa`**: PTW 响应的获取 GPA 信号。
|
||||||
|
|
||||||
## 二、测试用 Bundle 说明
|
## 二、测试用 Bundle 说明
|
||||||
|
|
||||||
| **TLBWrapper** | | |
|
- **`TLBWrapper`**
|
||||||
|----------------|------------------------------|---------------------|
|
- `clock`
|
||||||
|`clock` | | |
|
- `ctrl`
|
||||||
|`ctrl` | `reset` | |
|
- `reset`
|
||||||
| | `io_sfence_valid` | |
|
- `io_sfence_valid`
|
||||||
| | `io_hartId` | |
|
- `io_requestor_2_resp_ready`
|
||||||
| | `io_requestor_2_resp_ready` | |
|
- `io_requestor_2_resp_valid`
|
||||||
| | `io_requestor_2_resp_valid` | |
|
- `io_ptw_req_0_valid`
|
||||||
| | `io_ptw_req_0_valid` | |
|
- `io_ptw_req_1_valid`
|
||||||
| | `io_ptw_req_1_valid` | |
|
- `io_ptw_req_2_ready`
|
||||||
| | `io_ptw_req_2_ready` | |
|
- `io_ptw_req_2_valid`
|
||||||
| | `io_ptw_req_2_valid` | |
|
- `io_ptw_resp_valid`
|
||||||
| | `io_ptw_resp_valid` | |
|
- `io_ptw_resp_bits_s2xlate`
|
||||||
| | `io_ptw_resp_bits_s2xlate` | |
|
- `io_ptw_resp_bits_getGpa`
|
||||||
| | `io_ptw_resp_bits_getGpa` | |
|
- `sfence`
|
||||||
| `sfence` | `rs1` | |
|
- `rs1`
|
||||||
| | `rs2` | |
|
- `rs2`
|
||||||
| | `addr` | |
|
- `addr`
|
||||||
| | `id` | |
|
- `id`
|
||||||
| | `flushPipe` | |
|
- `flushPipe`
|
||||||
| | `hv` | |
|
- `hv`
|
||||||
| | `hg` | |
|
- `hg`
|
||||||
| `csr` | `satp` | `mode` |
|
- `csr`
|
||||||
| | | `asid` |
|
- `satp`
|
||||||
| | | `changed` |
|
- `mode`
|
||||||
| | `vsatp` | `mode` |
|
- `asid`
|
||||||
| | | `asid` |
|
- `changed`
|
||||||
| | | `changed` |
|
- `vsatp`
|
||||||
| | `hgatp` | `mode` |
|
- `mode`
|
||||||
| | | `vmid` |
|
- `asid`
|
||||||
| | | `changed` |
|
- `changed`
|
||||||
| | `priv` | `virt` |
|
- `hgatp`
|
||||||
| | | `imode` |
|
- `mode`
|
||||||
| `requestor_0` | `req` | `valid` |
|
- `vmid`
|
||||||
| | | `bits_vaddr` |
|
- `changed`
|
||||||
| | `resp` | `paddr_0` |
|
- `priv`
|
||||||
| | | `gpaddr_0` |
|
- `virt`
|
||||||
| | | `pbmt_0` |
|
- `imode`
|
||||||
| | | `miss` |
|
- `requestor_0`
|
||||||
| | | `idForVSnonLeafPTE` |
|
- `req`
|
||||||
| | | `excp_0_gpf_instr` |
|
- `valid`
|
||||||
| | | `excp_0_pf_instr` |
|
- `bits_vaddr`
|
||||||
| | | `excp_0_af_instr` |
|
- `resp`
|
||||||
| `requestor_1` | `req` | `valid` |
|
- `paddr_0`
|
||||||
| | | `bits_vaddr` |
|
- `gpaddr_0`
|
||||||
| | `resp` | `paddr_0` |
|
- `miss`
|
||||||
| | | `gpaddr_0` |
|
- `excp_0_gpf_instr`
|
||||||
| | | `pbmt_0` |
|
- `excp_0_pf_instr`
|
||||||
| | | `miss` |
|
- `excp_0_af_instr`
|
||||||
| | | `idForVSnonLeafPTE` |
|
- `requestor_1`
|
||||||
| | | `excp_0_gpf_instr` |
|
- `req`
|
||||||
| | | `excp_0_pf_instr` |
|
- `valid`
|
||||||
| | | `excp_0_af_instr` |
|
- `bits_vaddr`
|
||||||
| `requestor_0` | `req` | `valid` |
|
- `resp`
|
||||||
| | | `ready` |
|
- `paddr_0`
|
||||||
| | | `bits_vaddr` |
|
- `gpaddr_0`
|
||||||
| | `resp` | `paddr_0` |
|
- `miss`
|
||||||
| | | `gpaddr_0` |
|
- `excp_0_gpf_instr`
|
||||||
| | | `pbmt_0` |
|
- `excp_0_pf_instr`
|
||||||
| | | `miss` |
|
- `excp_0_af_instr`
|
||||||
| | | `idForVSnonLeafPTE` |
|
- `requestor_2`
|
||||||
| | | `excp_0_gpf_instr` |
|
- `req`
|
||||||
| | | `excp_0_pf_instr` |
|
- `valid`
|
||||||
| | | `excp_0_af_instr` |
|
- `ready`
|
||||||
| `flushPipe[3]` | | |
|
- `bits_vaddr`
|
||||||
| `ptw_req_0` | `vpn` | |
|
- `resp`
|
||||||
| | `s2xlate` | |
|
- `paddr_0`
|
||||||
| | `getGpa` | |
|
- `gpaddr_0`
|
||||||
| `ptw_req_1` | `vpn` | |
|
- `excp_0_gpf_instr`
|
||||||
| | `s2xlate` | |
|
- `excp_0_pf_instr`
|
||||||
| | `getGpa` | |
|
- `excp_0_af_instr`
|
||||||
| `ptw_req_2` | `vpn` | |
|
- `flushPipe[3]`
|
||||||
| | `s2xlate` | |
|
- `ptw_req_0`
|
||||||
| | `getGpa` | |
|
- `vpn`
|
||||||
| `ptw_resp_s1` | `entry_tag` | |
|
- `s2xlate`
|
||||||
| | `entry_asid` | |
|
- `getGpa`
|
||||||
| | `entry_vmid` | |
|
- `ptw_req_1`
|
||||||
| | `entry_n` | |
|
- `vpn`
|
||||||
| | `entry_pbmt` | |
|
- `s2xlate`
|
||||||
| | `entry_perm_d` | |
|
- `getGpa`
|
||||||
| | `entry_perm_a` | |
|
- `ptw_req_2`
|
||||||
| | `entry_perm_g` | |
|
- `vpn`
|
||||||
| | `entry_perm_u` | |
|
- `s2xlate`
|
||||||
| | `entry_perm_x` | |
|
- `getGpa`
|
||||||
| | `entry_perm_w` | |
|
- `ptw_resp_s1`
|
||||||
| | `entry_perm_r` | |
|
- `entry_tag`
|
||||||
| | `entry_level` | |
|
- `entry_asid`
|
||||||
| | `entry_v` | |
|
- `entry_vmid`
|
||||||
| | `entry_ppn` | |
|
- `entry_perm_*`
|
||||||
| | `addr_low` | |
|
- `entry_level`
|
||||||
| | `ppn_low_0` | |
|
- `entry_ppn`
|
||||||
| | `ppn_low_1` | |
|
- `addr_low`
|
||||||
| | `ppn_low_2` | |
|
- `ppn_low_*`
|
||||||
| | `ppn_low_3` | |
|
- `valididx_*`
|
||||||
| | `ppn_low_4` | |
|
- `pteidx_*`
|
||||||
| | `ppn_low_5` | |
|
- `pf`
|
||||||
| | `ppn_low_6` | |
|
- `af`
|
||||||
| | `ppn_low_7` | |
|
- `ptw_resp_s2`
|
||||||
| | `valididx_0` | |
|
- `entry_tag`
|
||||||
| | `valididx_1` | |
|
- `entry_vmid`
|
||||||
| | `valididx_2` | |
|
- `entry_perm_*`
|
||||||
| | `valididx_3` | |
|
- `entry_level`
|
||||||
| | `valididx_4` | |
|
- `gpf`
|
||||||
| | `valididx_5` | |
|
- `gaf`
|
||||||
| | `valididx_6` | |
|
|
||||||
| | `valididx_7` | |
|
|
||||||
| | `pteidx_0` | |
|
|
||||||
| | `pteidx_1` | |
|
|
||||||
| | `pteidx_2` | |
|
|
||||||
| | `pteidx_3` | |
|
|
||||||
| | `pteidx_4` | |
|
|
||||||
| | `pteidx_5` | |
|
|
||||||
| | `pteidx_6` | |
|
|
||||||
| | `pteidx_7` | |
|
|
||||||
| | `pf` | |
|
|
||||||
| | `af` | |
|
|
||||||
| `ptw_resp_s2` | `entry_tag` | |
|
|
||||||
| | `entry_vmid` | |
|
|
||||||
| | `entry_n` | |
|
|
||||||
| | `entry_pbmt` | |
|
|
||||||
| | `entry_ppn` | |
|
|
||||||
| | `entry_perm_d` | |
|
|
||||||
| | `entry_perm_a` | |
|
|
||||||
| | `entry_perm_g` | |
|
|
||||||
| | `entry_perm_u` | |
|
|
||||||
| | `entry_perm_x` | |
|
|
||||||
| | `entry_perm_w` | |
|
|
||||||
| | `entry_perm_r` | |
|
|
||||||
| | `entry_level` | |
|
|
||||||
| | `gpf` | |
|
|
||||||
| | `gaf` | |
|
|
||||||
|
|
||||||
## 三、测试用例格式(方便复制粘贴)
|
## 三、测试用例格式(方便复制粘贴)
|
||||||
|
|
||||||
```python
|
|
||||||
def test_TODO(tlb_fixture):
|
def test_TODO(tlb_fixture):
|
||||||
"""
|
"""
|
||||||
Func: TODO
|
Func: TODO
|
||||||
|
|
@ -327,4 +271,3 @@ def test_TODO(tlb_fixture):
|
||||||
tlb.dut.Step(2)
|
tlb.dut.Step(2)
|
||||||
|
|
||||||
# assert result
|
# assert result
|
||||||
```
|
|
||||||
|
|
|
||||||
|
|
@ -14,38 +14,4 @@
|
||||||
|
|
||||||
class consts():
|
class consts():
|
||||||
Width = 3
|
Width = 3
|
||||||
nRespDups = 1
|
nRespDups = 1
|
||||||
|
|
||||||
class BaseConstant(int):
|
|
||||||
"""特殊常量基类"""
|
|
||||||
__slots__ = ()
|
|
||||||
_name = ""
|
|
||||||
_value = None
|
|
||||||
|
|
||||||
def __new__(cls):
|
|
||||||
return int.__new__(cls, cls._value)
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return f"<{self._name}>"
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return self._name
|
|
||||||
|
|
||||||
def __eq__(self, other):
|
|
||||||
return other == self._value or other is self
|
|
||||||
|
|
||||||
class DontCareType(BaseConstant):
|
|
||||||
_name = "DONTCARE"
|
|
||||||
_value = 0
|
|
||||||
|
|
||||||
class Unused0Type(BaseConstant):
|
|
||||||
_name = "UNUSED_0"
|
|
||||||
_value = 0
|
|
||||||
|
|
||||||
class Unused1Type(BaseConstant):
|
|
||||||
_name = "UNUSED_1"
|
|
||||||
_value = 1
|
|
||||||
|
|
||||||
DONTCARE = DontCareType()
|
|
||||||
UNUSED0 = Unused0Type()
|
|
||||||
UNUSED1 = Unused1Type()
|
|
||||||
|
|
@ -88,7 +88,6 @@ class ControlBundle(toffee.Bundle):
|
||||||
signals = [
|
signals = [
|
||||||
"reset",
|
"reset",
|
||||||
"io_sfence_valid",
|
"io_sfence_valid",
|
||||||
"io_hartId",
|
|
||||||
"io_requestor_2_resp_ready",
|
"io_requestor_2_resp_ready",
|
||||||
"io_requestor_2_resp_valid",
|
"io_requestor_2_resp_valid",
|
||||||
"io_ptw_req_0_valid",
|
"io_ptw_req_0_valid",
|
||||||
|
|
@ -324,95 +323,15 @@ class TLBWrapper(toffee.Bundle):
|
||||||
req_2_valid, req_2_vaddr = self.rand_req2()
|
req_2_valid, req_2_vaddr = self.rand_req2()
|
||||||
return req_0_valid, req_0_vaddr, req_1_valid, req_1_vaddr, req_2_valid, req_2_vaddr
|
return req_0_valid, req_0_vaddr, req_1_valid, req_1_vaddr, req_2_valid, req_2_vaddr
|
||||||
|
|
||||||
def rand_ptw_resp(self, vpn, asid, s2xlate):
|
def gene_rand_ptw_resp(self, vpn, s2xlate):
|
||||||
"""
|
"""
|
||||||
generate random PTW response by s2xlate
|
generate random PTW response by s2xlate
|
||||||
"""
|
"""
|
||||||
# generate random input signals
|
self.ctrl.io_ptw_resp_valid = 1
|
||||||
randPPN = random.randint(0, 2 ** 36 - 1)
|
self.ctrl.io_ptw_resp_bits_s2xlate = s2xlate
|
||||||
randValididx = [random.choice([0,1]) for _ in range(8)]
|
# nos2xlate (s2xlate == 0b00)
|
||||||
randPPN_low = [random.randint(0, 2 ** 3 - 1) for _ in range(8)]
|
self.ptw_resp_s1.entry_tag = vpn >> 12
|
||||||
|
self.ptw_resp_s1.entry_asid
|
||||||
addr_low = vpn & 0b111
|
|
||||||
|
|
||||||
# assign to DUT
|
|
||||||
## ctrl signals
|
|
||||||
self.ctrl.io_ptw_resp_valid.value = 1
|
|
||||||
self.ctrl.io_ptw_resp_bits_s2xlate.value = s2xlate
|
|
||||||
## nos2xlate (s2xlate == 0b00)
|
|
||||||
if (s2xlate == 0b00):
|
|
||||||
self.ptw_resp_s1.entry_tag.value = vpn >> 3
|
|
||||||
self.ptw_resp_s1.entry_asid.value = asid
|
|
||||||
self.ptw_resp_s1.entry_vmid.value = DONTCARE
|
|
||||||
self.ptw_resp_s1.entry_n.value = UNUSED0
|
|
||||||
self.ptw_resp_s1.entry_pbmt.value = UNUSED0
|
|
||||||
self.ptw_resp_s1.entry_perm_d.value = UNUSED0
|
|
||||||
self.ptw_resp_s1.entry_perm_a.value = UNUSED0
|
|
||||||
self.ptw_resp_s1.entry_perm_g.value = UNUSED0
|
|
||||||
self.ptw_resp_s1.entry_perm_u.value = UNUSED0
|
|
||||||
self.ptw_resp_s1.entry_perm_x.value = UNUSED1
|
|
||||||
self.ptw_resp_s1.entry_perm_w.value = UNUSED0
|
|
||||||
self.ptw_resp_s1.entry_perm_r.value = UNUSED0
|
|
||||||
self.ptw_resp_s1.entry_level.value = UNUSED0
|
|
||||||
self.ptw_resp_s1.entry_v.value = 1
|
|
||||||
self.ptw_resp_s1.entry_ppn.value = randPPN >> 3
|
|
||||||
self.ptw_resp_s1.addr_low.value = addr_low
|
|
||||||
ppn_low_dict = {
|
|
||||||
0: self.ptw_resp_s1.ppn_low_0,
|
|
||||||
1: self.ptw_resp_s1.ppn_low_1,
|
|
||||||
2: self.ptw_resp_s1.ppn_low_2,
|
|
||||||
3: self.ptw_resp_s1.ppn_low_3,
|
|
||||||
4: self.ptw_resp_s1.ppn_low_4,
|
|
||||||
5: self.ptw_resp_s1.ppn_low_5,
|
|
||||||
6: self.ptw_resp_s1.ppn_low_6,
|
|
||||||
7: self.ptw_resp_s1.ppn_low_7
|
|
||||||
}
|
|
||||||
valididx_dict = {
|
|
||||||
0: self.ptw_resp_s1.valididx_0,
|
|
||||||
1: self.ptw_resp_s1.valididx_1,
|
|
||||||
2: self.ptw_resp_s1.valididx_2,
|
|
||||||
3: self.ptw_resp_s1.valididx_3,
|
|
||||||
4: self.ptw_resp_s1.valididx_4,
|
|
||||||
5: self.ptw_resp_s1.valididx_5,
|
|
||||||
6: self.ptw_resp_s1.valididx_6,
|
|
||||||
7: self.ptw_resp_s1.valididx_7
|
|
||||||
}
|
|
||||||
pteidx_dict = {
|
|
||||||
0: self.ptw_resp_s1.pteidx_0,
|
|
||||||
1: self.ptw_resp_s1.pteidx_1,
|
|
||||||
2: self.ptw_resp_s1.pteidx_2,
|
|
||||||
3: self.ptw_resp_s1.pteidx_3,
|
|
||||||
4: self.ptw_resp_s1.pteidx_4,
|
|
||||||
5: self.ptw_resp_s1.pteidx_5,
|
|
||||||
6: self.ptw_resp_s1.pteidx_6,
|
|
||||||
7: self.ptw_resp_s1.pteidx_7
|
|
||||||
}
|
|
||||||
for i in range(8):
|
|
||||||
if i == addr_low:
|
|
||||||
ppn_low_dict[i].value = randPPN & 0b111
|
|
||||||
valididx_dict[i].value = 1
|
|
||||||
else:
|
|
||||||
ppn_low_dict[i].value = randPPN_low[i]
|
|
||||||
valididx_dict[i].value = randValididx[i]
|
|
||||||
pteidx_dict[addr_low].value = 1
|
|
||||||
self.ptw_resp_s1.pf.value = UNUSED0
|
|
||||||
self.ptw_resp_s1.af.value = UNUSED0
|
|
||||||
## OnlyStage1 (s2xlate == 0b01)
|
|
||||||
elif (s2xlate == 0b01):
|
|
||||||
self.ptw_resp_s1.entry_tag.value = vpn >> 12
|
|
||||||
self.ptw_resp_s1.entry_asid.value = asid
|
|
||||||
# TODO
|
|
||||||
## OnlyStage2 (s2xlate == 0b10)
|
|
||||||
elif (s2xlate == 0b10):
|
|
||||||
self.ptw_resp_s1.entry_tag.value = vpn >> 12
|
|
||||||
self.ptw_resp_s1.entry_asid.value = asid
|
|
||||||
# TODO
|
|
||||||
## AllStage (s2xlate == 0b11)
|
|
||||||
else:
|
|
||||||
self.ptw_resp_s1.entry_tag.value = vpn >> 12
|
|
||||||
self.ptw_resp_s1.entry_asid.value = asid
|
|
||||||
# TODO
|
|
||||||
return randPPN
|
|
||||||
|
|
||||||
class TLBrwWrapper(toffee.Bundle):
|
class TLBrwWrapper(toffee.Bundle):
|
||||||
"""
|
"""
|
||||||
|
|
@ -513,4 +432,4 @@ class TLBrwWrapper(toffee.Bundle):
|
||||||
self.dut.Step(10)
|
self.dut.Step(10)
|
||||||
self.dut.reset.value = 0
|
self.dut.reset.value = 0
|
||||||
self.dut.Step(2)
|
self.dut.Step(2)
|
||||||
# print(">>> RESET FINISHED !")
|
# print(">>> RESET FINISHED !")
|
||||||
|
|
@ -19,7 +19,7 @@ import inspect
|
||||||
# Running the following test case will show a pass:
|
# Running the following test case will show a pass:
|
||||||
def test_receive_ptw_resp_nonstage(tlb_fixture):
|
def test_receive_ptw_resp_nonstage(tlb_fixture):
|
||||||
"""
|
"""
|
||||||
Func: receive PTW response under nonstage condition and stored it into TLB entry
|
Func: TODO
|
||||||
subfunc1: TODO
|
subfunc1: TODO
|
||||||
"""
|
"""
|
||||||
# connect to fixture
|
# connect to fixture
|
||||||
|
|
@ -38,30 +38,10 @@ def test_receive_ptw_resp_nonstage(tlb_fixture):
|
||||||
# add clock
|
# add clock
|
||||||
tlb.dut.xclock.StepRis(lambda _: g.sample())
|
tlb.dut.xclock.StepRis(lambda _: g.sample())
|
||||||
# start
|
# start
|
||||||
for _ in range(1000):
|
for _ in range(10000):
|
||||||
for _ in range(30):
|
# add signal and assign to dut
|
||||||
# add signal and assign to dut
|
|
||||||
vaddr = random.randint(0, 2 ** 50 - 1)
|
|
||||||
asid = random.randint(0, 2 ** 16 - 1)
|
|
||||||
vpn = vaddr >> 12
|
|
||||||
offset = vaddr & 0xfff
|
|
||||||
s2xlate = 0b00
|
|
||||||
ppn = tlb.rand_ptw_resp(vpn, asid, s2xlate)
|
|
||||||
|
|
||||||
tlb.csr.satp.asid.value = asid
|
# step to next cycle
|
||||||
|
tlb.dut.Step(2)
|
||||||
|
|
||||||
# step to next cycle
|
# assert result
|
||||||
tlb.dut.Step()
|
|
||||||
|
|
||||||
# check whether PTW resp is stored
|
|
||||||
tlb.requestor_0.req.valid.value = 1
|
|
||||||
tlb.requestor_0.req.bits_vaddr.value = (vpn << 12) | offset
|
|
||||||
|
|
||||||
# step to next cycle
|
|
||||||
tlb.dut.Step(2)
|
|
||||||
|
|
||||||
# assert result
|
|
||||||
assert(tlb.requestor_0.resp.paddr_0.value == ((ppn << 12) | offset))
|
|
||||||
assert(tlb.requestor_0.resp.miss.value == 0)
|
|
||||||
# reset
|
|
||||||
tlb.reset()
|
|
||||||
Loading…
Reference in New Issue