Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 34 additions & 21 deletions src/main/scala/IMSIC.scala
Original file line number Diff line number Diff line change
Expand Up @@ -757,40 +757,53 @@ class TLRegIMSIC(
val msiio = IO(Flipped(new MSITransBundle(params))) // backpressure signal for axi4bus, from imsic working on cpu clock
private val reggen = Module(new RegGen(params, beatBytes))
// ---- instance sync fifo ----//
// --- fifo wdata: {vector_valid,setipnum}, fifo wren: |vector_valid---//
val FifoDataWidth = params.MSI_INFO_WIDTH
val fifo_wdata = Wire(Valid(UInt(FifoDataWidth.W)))

// depth:8, data width: FifoDataWidth
private val fifo_sync = Module(new Queue(UInt(FifoDataWidth.W), 8))
// define about fifo write
fifo_wdata.bits := reggen.io.seteipnum
fifo_wdata.valid := reggen.io.valid
fifo_sync.io.enq.valid := fifo_wdata.valid
fifo_sync.io.enq.bits := fifo_wdata.bits
val stageValid = RegInit(false.B)
val stageBits = Reg(UInt(FifoDataWidth.W))
val stageReady = !stageValid || fifo_sync.io.enq.ready
fifo_sync.io.enq.valid := stageValid
fifo_sync.io.enq.bits := stageBits
when(stageReady) {
stageValid := reggen.io.valid
when(reggen.io.valid) {
stageBits := reggen.io.seteipnum
}
}
// fifo rd,controlled by msi_vld_ack from imsic working on csr clock.
// msi_vld_ack_soc: sync result with soc clock
val msi_vld_ack_soc = WireInit(false.B)
val msi_vld_ack_cpu = msiio.vld_ack
val msi_vld_req = RegInit(false.B)
val s_idle :: s_waitAckSet :: s_waitAckClr :: Nil = Enum(3)
val handshakeState = RegInit(s_idle)
when(params.EnableImsicAsyncBridge.B) {
msi_vld_ack_soc := AsyncResetSynchronizerShiftReg(msi_vld_ack_cpu, 3, 0)
}.otherwise {
msi_vld_ack_soc := msi_vld_ack_cpu
}
fifo_sync.io.deq.ready := ~msi_vld_req
// generate the msi_vld_req: high if ~empty,low when msi_vld_ack_soc
fifo_sync.io.deq.ready := handshakeState === s_idle
msiio.vld_req := msi_vld_req
val msi_vld_ack_soc_1f = RegNext(msi_vld_ack_soc)
val msi_vld_ack_soc_ris = msi_vld_ack_soc & (~msi_vld_ack_soc_1f)
// val fifo_empty = ~fifo_sync.io.deq.valid
// msi_vld_req : high when fifo empty is false, low when ack is high. and io.deq.valid := ~empty
when(msi_vld_ack_soc_ris) {
msi_vld_req := false.B
}.elsewhen(fifo_sync.io.deq.valid === true.B) {
msi_vld_req := true.B
}.otherwise {
msi_vld_req := msi_vld_req
switch(handshakeState) {
is(s_idle) {
when(fifo_sync.io.deq.fire) {
msi_vld_req := true.B
handshakeState := s_waitAckSet
}
}
is(s_waitAckSet) {
when(msi_vld_ack_soc) {
msi_vld_req := false.B
handshakeState := s_waitAckClr
}
}
is(s_waitAckClr) {
when(!msi_vld_ack_soc) {
handshakeState := s_idle
}
}
}

// get the msi interrupt ID info
Expand All @@ -803,7 +816,7 @@ class TLRegIMSIC(
}
// port connect: io.valid is interrupt file index info.
msiio.data := msi_id_data
val backpress = fifo_sync.io.enq.ready
val backpress = stageReady
(intfileFromMems zip reggen.regmapIOs).map {
case (intfileFromMem, regmapIO) => intfileFromMem.regmap(regmapIO._1, regmapIO._2, backpress)
}
Expand Down Expand Up @@ -931,7 +944,7 @@ class RegGen(
// j: index is 0 for m file for seq[0],index is 0~params.geilen for S intFile for seq[1]: S, G1, G2, ...
val maps = (0 until intFilesNum).map { j =>
val flati = i + j // seq[0]:0+0=0;seq[1]:(0~geilen)+1
val seteipnum = WireInit(0.U.asTypeOf(Valid(UInt(params.imsicIntSrcWidth.W))));
val seteipnum = WireInit(0.U.asTypeOf(Valid(UInt(params.imsicIntSrcWidth.W)))); /*for debug*/
dontTouch(seteipnum)
valids(flati) := seteipnum.valid
seteipnums(flati) := seteipnum.bits
Expand Down
12 changes: 6 additions & 6 deletions src/main/scala/common.scala
Original file line number Diff line number Diff line change
Expand Up @@ -518,16 +518,16 @@ case class TLRegMapperNode(
// copy a.bits.{source, size} to d.bits.{source, size}
val sourceReg = RegInit(0.U.asTypeOf(a.bits.source))
val sizeReg = RegInit(0.U.asTypeOf(a.bits.size))
when (a.valid) {
when (a.fire) {
sourceReg := a.bits.source
sizeReg := a.bits.size
}

// No flow control needed
in.valid := a.valid
in.valid := a.valid && (in.bits.read || backpress)
a.ready := Mux(in.bits.read, in.ready, (backpress & in.ready))
d.valid := Mux(out.bits.read, out.valid, (backpress & out.valid))
out.ready := d.ready
d.valid := out.valid
out.ready := d.ready && (out.bits.read || backpress)

// We must restore the size to enable width adapters to work
d.bits := edge.AccessAck(toSource = sourceReg, lgSize = sizeReg)
Expand Down Expand Up @@ -579,7 +579,7 @@ case class AXI4RegMapperNode(
dontTouch(w.bits)
dontTouch(b.bits)
dontTouch(r.bits)

// Prefer to execute reads first
in.valid := ar.valid || (backpress && aw.valid && w.valid)
ar.ready := in.ready
Expand Down Expand Up @@ -630,4 +630,4 @@ case class AXI4RegMapperNode(
b.bits.resp := AXI4Parameters.RESP_OKAY
b.bits.echo :<= awEchoReg
}
}
}
3 changes: 2 additions & 1 deletion test/aplic/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
GEN_DIR := $(if $(wildcard ../../gen/filelist.f),$(realpath ../../gen),$(realpath ../../../gen))
TOPLEVEL = TLAIA
VERILOG_SOURCES += $(addprefix $(realpath ../../gen)/, $(shell cat ../../gen/filelist.f))
VERILOG_SOURCES += $(addprefix $(GEN_DIR)/, $(shell cat $(GEN_DIR)/filelist.f))
SIM_BUILD = ../sim_build
include ../Makefile.common
29 changes: 25 additions & 4 deletions test/aplic/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@
from cocotb.triggers import RisingEdge, FallingEdge, Edge
from common import *


async def init_aplic_dut(dut):
dut.reset.value = 1
for _ in range(10):
await RisingEdge(dut.clock)
dut.reset.value = 0
dut.toaia_0_d_ready.value = 1
await RisingEdge(dut.clock)

@cocotb.test()
async def aplic_write_read_test(dut):
# Start the clock
Expand Down Expand Up @@ -80,6 +89,11 @@ async def write_read_check_1(dut, addr, data):
async def aplic_set_clr_test(dut):
# Start the clock
cocotb.start_soon(Clock(dut.clock, 1, units="ns").start())
await init_aplic_dut(dut)

# Standalone set/clr tests need their sources marked active first.
for int_num in (27, 54, 63):
await a_put_full32(dut, aplic_m_base_addr+offset_sourcecfg+(int_num-1)*4, sourcecfg_sm_edge1)

# setienum 0, which should be ignored
ie0 = await a_get32(dut, aplic_m_base_addr+offset_seties)
Expand Down Expand Up @@ -120,12 +134,13 @@ async def aplic_set_clr_test(dut):
async def aplic_triggered_int_test(dut):
# Start the clock
cocotb.start_soon(Clock(dut.clock, 1, units="ns").start())
await init_aplic_dut(dut)

# int sources
async def expect_intSrcsTriggered_2(dut, value):
for _ in range(10):
await RisingEdge(dut.clock)
if dut.aplic.aplic.domains_0.intSrcsTriggered_2 == value:
if int(dut.aplic.aplic.domains_0.intSrcsTriggered_2.value) == value:
break
else:
assert False, f"Timeout waiting for dut.aplic.intSrcsTriggered_2"
Expand All @@ -134,7 +149,7 @@ async def expect_intSrcsTriggered_2(dut, value):
await a_put_full32(dut, aplic_m_base_addr+offset_sourcecfg+1*4, sourcecfg_sm_edge1)
await FallingEdge(dut.clock)
dut.intSrcs_2.value = 0
assert dut.aplic.aplic.domains_0.intSrcsTriggered_2 == 0
assert int(dut.aplic.aplic.domains_0.intSrcsTriggered_2.value) == 0
await FallingEdge(dut.clock)
dut.intSrcs_2.value = 1
await expect_intSrcsTriggered_2(dut, 1)
Expand All @@ -161,6 +176,7 @@ async def expect_intSrcsTriggered_2(dut, value):
async def aplic_in_clrips_test(dut):
# Start the clock
cocotb.start_soon(Clock(dut.clock, 1, units="ns").start())
await init_aplic_dut(dut)

await a_put_full32(dut, aplic_m_base_addr+offset_seties, 0)
rect_before = await a_get32(dut, aplic_m_base_addr+offset_in_clrips+0*4)
Expand Down Expand Up @@ -197,16 +213,19 @@ async def aplic_in_clrips_test(dut):
async def aplic_msi_test(dut):
# Start the clock
cocotb.start_soon(Clock(dut.clock, 1, units="ns").start())
await init_aplic_dut(dut)

async def expect_int_num(dut, num, addr):
for _ in range(0,10):
await RisingEdge(dut.clock)
if dut.aplic.auto_toIMSIC_out_a_bits_data == num:
assert dut.aplic.auto_toIMSIC_out_a_bits_address == addr
if int(dut.aplic.auto_toIMSIC_out_a_bits_data.value) == num:
assert int(dut.aplic.auto_toIMSIC_out_a_bits_address.value) == addr
break
else:
assert False, f"Timeout waiting for dut.aplic.auto_toIMSIC_out_a_bits_data"

await a_put_full32(dut, aplic_m_base_addr+offset_domaincfg, 0x80000104)

# # setipnum 0, which should be ignored
# ip0 = await a_get32(dut, base_addr+offset_setips)
# await a_put_full32(dut, base_addr+offset_setipnum, 0)
Expand All @@ -217,6 +236,7 @@ async def expect_int_num(dut, num, addr):
int_num = 27
eiid = 0xCA
guest_id = 2
await a_put_full32(dut, aplic_m_base_addr+offset_sourcecfg+(int_num-1)*4, sourcecfg_sm_edge1)
await a_put_full32(dut, aplic_m_base_addr+offset_targets+(int_num-1)*4, (guest_id<<12)|eiid)
await a_put_full32(dut, aplic_m_base_addr+offset_seties+0*4, 0xffffffff)
await a_put_full32(dut, aplic_m_base_addr+offset_setipnum, int_num)
Expand All @@ -229,6 +249,7 @@ async def expect_int_num(dut, num, addr):
# setipnum ip1
int_num = 63
eiid = 0xEF
await a_put_full32(dut, aplic_m_base_addr+offset_sourcecfg+(int_num-1)*4, sourcecfg_sm_edge1)
await a_put_full32(dut, aplic_m_base_addr+offset_targets+(int_num-1)*4, eiid)
await a_put_full32(dut, aplic_m_base_addr+offset_seties+1*4, 1<<(int_num-32))
await a_put_full32(dut, aplic_m_base_addr+offset_setipnum, int_num)
Expand Down
37 changes: 31 additions & 6 deletions test/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ async def delay_fifo(dut):
op_access_ack_data = 1
async def a_op(dut, addr, data, op, mask, size) -> None:
await FallingEdge(dut.clock)
while not dut.toaia_0_a_ready:
while not int(dut.toaia_0_a_ready.value):
await FallingEdge(dut.clock)
dut.toaia_0_a_valid.value = 1
dut.toaia_0_a_bits_opcode.value = op
Expand All @@ -56,15 +56,15 @@ async def a_put_full32(dut, addr, data) -> None:
await a_op32(dut, addr, data, op_put_full)
for _ in range(10):
await RisingEdge(dut.clock)
if dut.toaia_0_d_bits_opcode == op_access_ack and dut.toaia_0_d_valid == 1:
if int(dut.toaia_0_d_bits_opcode.value) == op_access_ack and int(dut.toaia_0_d_valid.value) == 1:
break
else:
assert False, f"Timeout waiting for op_access_ack"
async def a_get32(dut, addr) -> int:
await a_op32(dut, addr, 0, op_get)
for _ in range(10):
await RisingEdge(dut.clock)
if dut.toaia_0_d_bits_opcode == op_access_ack_data and dut.toaia_0_d_valid == 1:
if int(dut.toaia_0_d_bits_opcode.value) == op_access_ack_data and int(dut.toaia_0_d_valid.value) == 1:
break
else:
assert False, f"Timeout waiting for op_access_ack_data"
Expand All @@ -81,15 +81,15 @@ async def interrupt(dut, i):
if EnableImsicAsyncBridge ==1 :
for _ in range(15):
await FallingEdge(dut.clock)
if dut.toCSR0_topeis_0 == wrap_topei(i):
if int(dut.toCSR0_topeis_0.value) == wrap_topei(i):
break
else:
assert False, f"Timeout waiting for toCSR0_topeis_0 == wrap_topei({i})"
else :
for _ in range(10):
await FallingEdge(dut.clock)
await FallingEdge(dut.clock)
if dut.toCSR0_topeis_0 == wrap_topei(i):
if int(dut.toCSR0_topeis_0.value) == wrap_topei(i):
break
else:
assert False, f"Timeout waiting for toCSR0_topeis_0 == wrap_topei({i})"
Expand Down Expand Up @@ -122,7 +122,7 @@ async def s_int(dut, intnum, imsicID=1):

async def v_int_vgein(dut, intnum, imsicID=1, guestID=2):
"""Issue an interrupt to the VS-mode interrupt file with vgein2."""
await a_put_full32(dut, imsic_sg_base_addr+0x8000*imsicID + 0x1000*(1+guestID), intnum)
await a_put_full32(dut, imsic_sg_base_addr+0x8000*imsicID + 0x1000*guestID, intnum)
await RisingEdge(dut.clock)

async def claim(dut, imsicID=1):
Expand All @@ -138,6 +138,26 @@ def wrap_topei(in_):
out = extract | (extract << 16)
return out


async def wait_for_topei(dut, signal, expected, cycles=40, label=None):
for _ in range(cycles):
if int(signal.value) == expected:
return
await FallingEdge(dut.clock)
actual = int(signal.value)
name = label if label is not None else signal._name
assert False, f"Timeout waiting for {name} == {expected:#x}, got {actual:#x}"


async def wait_for_value(dut, signal, expected, cycles=10, label=None):
for _ in range(cycles):
if int(signal.value) == expected:
return
await FallingEdge(dut.clock)
actual = int(signal.value)
name = label if label is not None else signal._name
assert False, f"Timeout waiting for {name} == {expected:#x}, got {actual:#x}"

async def write_csr_op(dut, miselect, data, op, imsicID=1):
fromCSRx_addr_valid = getattr(dut, f"fromCSR{imsicID}_addr_valid" )
fromCSRx_addr_bits = getattr(dut, f"fromCSR{imsicID}_addr_bits_addr" )
Expand All @@ -160,11 +180,16 @@ async def write_csr(dut, miselect, data, imsicID=1):
async def read_csr(dut, miselect, imsicID=1):
fromCSRx_addr_valid = getattr(dut, f"fromCSR{imsicID}_addr_valid")
fromCSRx_addr_bits = getattr(dut, f"fromCSR{imsicID}_addr_bits_addr" )
toCSRx_rdata_valid = getattr(dut, f"toCSR{imsicID}_rdata_valid")
toCSRx_rdata_bits = getattr(dut, f"toCSR{imsicID}_rdata_bits")
await FallingEdge(dut.clock)
fromCSRx_addr_valid.value = 1
fromCSRx_addr_bits.value = miselect
await FallingEdge(dut.clock)
rvalid = int(toCSRx_rdata_valid.value)
rdata = int(toCSRx_rdata_bits.value)
fromCSRx_addr_valid.value = 0
return rvalid, rdata

async def select_m_intfile(dut, imsicID=1):
fromCSRx_priv = getattr(dut, f"fromCSR{imsicID}_addr_bits_priv")
Expand Down
3 changes: 2 additions & 1 deletion test/imsic/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
GEN_DIR := $(if $(wildcard ../../gen/filelist.f),$(realpath ../../gen),$(realpath ../../../gen))
TOPLEVEL = TLAIA
VERILOG_SOURCES += $(addprefix $(realpath ../../gen)/, $(shell cat ../../gen/filelist.f))
VERILOG_SOURCES += $(addprefix $(GEN_DIR)/, $(shell cat $(GEN_DIR)/filelist.f))
SIM_BUILD = ../sim_build
include ../Makefile.common
Loading
Loading