[PyCDE] Support for ESI MMIO service -- read side only (#6590)

Add support for the MMIO ESI service to PyCDE. Most implementations of this service will embed the compressed manifest, which this PR is intended to support. So let's just expose the read service for now.
This commit is contained in:
John Demme 2024-01-17 21:04:25 -08:00 committed by GitHub
parent 90f2bea727
commit 14b8450bc5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 48 additions and 14 deletions

View File

@ -4,10 +4,10 @@
from .common import (AppID, Input, Output, _PyProxy, PortError)
from .module import Generator, Module, ModuleLikeBuilderBase, PortProxyBase
from .signals import BundleSignal, ChannelSignal, Signal, _FromCirctValue
from .signals import BundleSignal, ChannelSignal, Signal, Struct, _FromCirctValue
from .system import System
from .types import (Bits, Bundle, BundledChannel, Channel, ChannelDirection,
Type, types, _FromCirctType)
StructType, Type, types, UInt, _FromCirctType)
from .circt import ir
from .circt.dialects import esi as raw_esi, hw, msft
@ -473,6 +473,21 @@ class PureModule(Module):
esi.ESIPureModuleParamOp(name, type_attr)
@ServiceDecl
class MMIO:
"""ESI standard service to request access to an MMIO region."""
read = ServiceDecl.From(
Bundle([
BundledChannel("offset", ChannelDirection.TO, Bits(32)),
BundledChannel("data", ChannelDirection.FROM, Bits(32))
]))
@staticmethod
def _op(sym_name: ir.StringAttr):
return raw_esi.MMIOServiceDeclOp(sym_name)
def package(sys: System):
"""Package all ESI collateral."""

View File

@ -1,11 +1,12 @@
# RUN: rm -rf %t
# RUN: %PYTHON% %s %t 2>&1 | FileCheck %s
from pycde import (Clock, Input, InputChannel, OutputChannel, Module, generator,
types)
from pycde import (Clock, Input, InputChannel, OutputChannel, Module, System,
generator, types)
from pycde import esi
from pycde.common import AppID, Output, RecvBundle, SendBundle
from pycde.constructs import Wire
from pycde.esi import MMIO
from pycde.types import (Bits, Bundle, BundledChannel, Channel,
ChannelDirection, ChannelSignaling, UInt, ClockType)
from pycde.testing import unittestmodule
@ -126,3 +127,23 @@ class RecvBundleTest(Module):
def build(self):
to_channels = self.b_recv.unpack(resp=self.i1_in)
self.s1_out = to_channels['req']
# CHECK-LABEL: hw.module @MMIOReq()
# CHECK-NEXT: %c0_i32 = hw.constant 0 : i32
# CHECK-NEXT: %false = hw.constant false
# CHECK-NEXT: [[B:%.+]] = esi.service.req.to_client <@MMIO::@read>(#esi.appid<"mmio_req">) : !esi.bundle<[!esi.channel<i32> to "offset", !esi.channel<i32> from "data"]>
# CHECK-NEXT: %chanOutput, %ready = esi.wrap.vr %c0_i32, %false : i32
# CHECK-NEXT: %offset = esi.bundle.unpack %chanOutput from [[B]] : !esi.bundle<[!esi.channel<i32> to "offset", !esi.channel<i32> from "data"]>
@unittestmodule(esi_sys=True)
class MMIOReq(Module):
@generator
def build(ports):
c32 = Bits(32)(0)
c1 = Bits(1)(0)
read_bundle = MMIO.read(AppID("mmio_req"))
data, _ = Channel(Bits(32)).wrap(c32, c1)
_ = read_bundle.unpack(data=data)

View File

@ -89,10 +89,9 @@ void MMIOServiceDeclOp::getPortList(SmallVectorImpl<ServicePortInfo> &ports) {
ServicePortInfo::Direction::toClient,
ChannelBundleType::get(
ctxt,
{BundledChannel{StringAttr::get(ctxt, "offset"),
ChannelDirection::from,
{BundledChannel{StringAttr::get(ctxt, "offset"), ChannelDirection::to,
ChannelType::get(ctxt, IntegerType::get(ctxt, 32))},
BundledChannel{StringAttr::get(ctxt, "data"), ChannelDirection::to,
BundledChannel{StringAttr::get(ctxt, "data"), ChannelDirection::from,
ChannelType::get(ctxt, IntegerType::get(ctxt, 32))}},
/*resettable=*/UnitAttr())});
// Write only port.
@ -101,10 +100,9 @@ void MMIOServiceDeclOp::getPortList(SmallVectorImpl<ServicePortInfo> &ports) {
ServicePortInfo::Direction::toClient,
ChannelBundleType::get(
ctxt,
{BundledChannel{StringAttr::get(ctxt, "offset"),
ChannelDirection::from,
{BundledChannel{StringAttr::get(ctxt, "offset"), ChannelDirection::to,
ChannelType::get(ctxt, IntegerType::get(ctxt, 32))},
BundledChannel{StringAttr::get(ctxt, "data"), ChannelDirection::from,
BundledChannel{StringAttr::get(ctxt, "data"), ChannelDirection::to,
ChannelType::get(ctxt, IntegerType::get(ctxt, 32))}},
/*resettable=*/UnitAttr())});
}

View File

@ -205,11 +205,11 @@ hw.module @CallableAccel1(in %clk: !seq.clock, in %rst: i1) {
}
esi.service.std.mmio @mmio
!mmioReq = !esi.bundle<[!esi.channel<i32> from "offset", !esi.channel<i32> to "data"]>
!mmioReq = !esi.bundle<[!esi.channel<i32> to "offset", !esi.channel<i32> from "data"]>
// CONN-LABEL: hw.module @MMIOManifest(in %clk : !seq.clock, in %rst : i1, in %manifest : !esi.bundle<[!esi.channel<i32> from "offset", !esi.channel<i32> to "data"]>) {
// CONN-NEXT: esi.manifest.req #esi.appid<"manifest">, <@mmio::@read> std "esi.service.std.mmio", toClient, !esi.bundle<[!esi.channel<i32> from "offset", !esi.channel<i32> to "data"]>
// CONN-NEXT: %data = esi.bundle.unpack %data from %manifest : !esi.bundle<[!esi.channel<i32> from "offset", !esi.channel<i32> to "data"]>
// CONN-LABEL: hw.module @MMIOManifest(in %clk : !seq.clock, in %rst : i1, in %manifest : !esi.bundle<[!esi.channel<i32> to "offset", !esi.channel<i32> from "data"]>) {
// CONN-NEXT: esi.manifest.req #esi.appid<"manifest">, <@mmio::@read> std "esi.service.std.mmio", toClient, !esi.bundle<[!esi.channel<i32> to "offset", !esi.channel<i32> from "data"]>
// CONN-NEXT: %offset = esi.bundle.unpack %offset from %manifest : !esi.bundle<[!esi.channel<i32> to "offset", !esi.channel<i32> from "data"]>
hw.module @MMIOManifest(in %clk: !seq.clock, in %rst: i1) {
%req = esi.service.req.to_client <@mmio::@read> (#esi.appid<"manifest">) : !mmioReq
%loopback = esi.bundle.unpack %loopback from %req : !mmioReq