mirror of https://github.com/llvm/circt.git
407 lines
18 KiB
Python
407 lines
18 KiB
Python
# RUN: rm -rf %t
|
|
# RUN: %PYTHON% %s %t 2>&1 | FileCheck %s
|
|
|
|
from pycde import (Clock, Input, InputChannel, Output, OutputChannel, Module,
|
|
Reset, generator, types)
|
|
from pycde import esi
|
|
from pycde.common import AppID, Constant, RecvBundle, SendBundle
|
|
from pycde.constructs import Wire
|
|
from pycde.esi import HostMem, MMIO
|
|
from pycde.module import Metadata
|
|
from pycde.support import _obj_to_attribute, optional_dict_to_dict_attr
|
|
from pycde.types import (Any, Bits, Bundle, BundledChannel, Channel,
|
|
ChannelDirection, ChannelSignaling, UInt, StructType,
|
|
ClockType)
|
|
from pycde.testing import unittestmodule
|
|
|
|
# CHECK: Channel<UInt<4>, ValidReady>
|
|
print(Channel(UInt(4)))
|
|
|
|
# CHECK: Channel<UInt<4>, FIFO>
|
|
print(Channel(UInt(4), ChannelSignaling.FIFO))
|
|
|
|
# CHECK: Channel<UInt<4>, ValidReady(1)>
|
|
print(Channel(UInt(4), ChannelSignaling.ValidReady, 1))
|
|
|
|
TestBundle = Bundle([
|
|
BundledChannel("resp", ChannelDirection.FROM, Bits(16)),
|
|
BundledChannel("req", ChannelDirection.TO, Bits(24))
|
|
])
|
|
|
|
TestFromBundle = Bundle([BundledChannel("ch1", ChannelDirection.TO, Bits(32))])
|
|
|
|
# CHECK: foo
|
|
print(AppID("foo"))
|
|
|
|
# CHECK: {{^}}#esi.appid<"foo">{{$}}
|
|
print(_obj_to_attribute(AppID("foo")))
|
|
|
|
# CHECK: {bar = 6 : i64, foo = 5 : i64}
|
|
print(optional_dict_to_dict_attr({"foo": 5, "bar": 6}))
|
|
# CHECK: {}
|
|
print(optional_dict_to_dict_attr(None))
|
|
|
|
|
|
@esi.ServiceDecl
|
|
class HostComms:
|
|
req_resp = TestBundle
|
|
from_host = TestFromBundle
|
|
|
|
|
|
# CHECK: esi.manifest.sym @LoopbackInOutTop name "LoopbackInOut" {{.*}}version "0.1" {bar = "baz", foo = 1 : i64}
|
|
# CHECK: esi.manifest.constants @LoopbackInOutTop {c1 = 54 : ui8}
|
|
|
|
|
|
# CHECK-LABEL: hw.module @LoopbackInOutTop(in %clk : !seq.clock, in %rst : i1)
|
|
# CHECK: esi.service.instance #esi.appid<"cosim"[0]> svc @HostComms impl as "cosim"(%clk, %rst) : (!seq.clock, i1) -> ()
|
|
# CHECK: [[B0:%.+]] = esi.service.req <@HostComms::@req_resp>(#esi.appid<"loopback_inout"[0]>) : !esi.bundle<[!esi.channel<i16> from "resp", !esi.channel<i24> to "req"]>
|
|
# CHECK: %req = esi.bundle.unpack %chanOutput from [[B0]] : !esi.bundle<[!esi.channel<i16> from "resp", !esi.channel<i24> to "req"]>
|
|
# CHECK: %rawOutput, %valid = esi.unwrap.vr %req, %ready : i24
|
|
# CHECK: [[R0:%.+]] = comb.extract %rawOutput from 0 : (i24) -> i16
|
|
# CHECK: %chanOutput, %ready = esi.wrap.vr [[R0]], %valid : i16
|
|
@unittestmodule(print=True)
|
|
class LoopbackInOutTop(Module):
|
|
clk = Clock()
|
|
rst = Input(types.i1)
|
|
|
|
metadata = Metadata(
|
|
name="LoopbackInOut",
|
|
version="0.1",
|
|
misc={
|
|
"foo": 1,
|
|
"bar": "baz"
|
|
},
|
|
)
|
|
|
|
c1 = Constant(UInt(8), 54)
|
|
|
|
@generator
|
|
def construct(self):
|
|
# Use Cosim to implement the 'HostComms' service.
|
|
esi.Cosim(HostComms, self.clk, self.rst)
|
|
|
|
loopback = Wire(types.channel(types.i16))
|
|
call_bundle = HostComms.req_resp(AppID("loopback_inout", 0))
|
|
froms = call_bundle.unpack(resp=loopback)
|
|
from_host = froms['req']
|
|
|
|
ready = Wire(types.i1)
|
|
wide_data, valid = from_host.unwrap(ready)
|
|
data = wide_data[0:16]
|
|
data_chan, data_ready = loopback.type.wrap(data, valid)
|
|
ready.assign(data_ready)
|
|
loopback.assign(data_chan)
|
|
|
|
|
|
CallBundle = Bundle([
|
|
BundledChannel("renamed_result", ChannelDirection.FROM, Bits(16)),
|
|
BundledChannel("args", ChannelDirection.TO, Bits(24))
|
|
])
|
|
|
|
|
|
# CHECK-LABEL: hw.module @LoopbackCoercedCall(in %clk : !seq.clock, in %rst : i1, out call : !esi.bundle<[!esi.channel<i16> from "renamed_result", !esi.channel<i24> to "args"]>)
|
|
# CHECK: [[REQ:%.+]] = esi.service.req <@_FuncService::@call>(#esi.appid<"loopback_coerced">) : !esi.bundle<[!esi.channel<i24> to "arg", !esi.channel<i16> from "result"]>
|
|
# CHECK: %arg = esi.bundle.unpack %renamed_result from [[REQ]] : !esi.bundle<[!esi.channel<i24> to "arg", !esi.channel<i16> from "result"]>
|
|
# CHECK: %bundle, %renamed_result = esi.bundle.pack %arg : !esi.bundle<[!esi.channel<i16> from "renamed_result", !esi.channel<i24> to "args"]>
|
|
@unittestmodule()
|
|
class LoopbackCoercedCall(Module):
|
|
clk = Clock()
|
|
rst = Reset()
|
|
call = Output(CallBundle)
|
|
|
|
@generator
|
|
def construct(ports):
|
|
ports.call = esi.FuncService.get(name=AppID("loopback_coerced"),
|
|
bundle_type=CallBundle)
|
|
|
|
|
|
# CHECK-LABEL: hw.module @LoopbackCall(in %clk : !seq.clock, in %rst : i1) attributes {output_file = #hw.output_file<"LoopbackCall.sv", includeReplicatedOps>} {
|
|
# CHECK-NEXT: [[R2:%.+]] = esi.buffer %clk, %rst, %chanOutput {stages = 1 : i64} : !esi.channel<i16> -> !esi.channel<i16, FIFO>
|
|
# CHECK-NEXT: [[R0:%.+]] = esi.service.req <@_FuncService::@call>(#esi.appid<"loopback">) : !esi.bundle<[!esi.channel<i24> to "arg", !esi.channel<i16, FIFO> from "result"]>
|
|
# CHECK-NEXT: %arg = esi.bundle.unpack [[R2]] from [[R0]] : !esi.bundle<[!esi.channel<i24> to "arg", !esi.channel<i16, FIFO> from "result"]>
|
|
# CHECK-NEXT: %rawOutput, %valid = esi.unwrap.vr %arg, %ready : i24
|
|
# CHECK-NEXT: [[R1:%.+]] = comb.extract %rawOutput from 0 : (i24) -> i16
|
|
# CHECK-NEXT: %chanOutput, %ready = esi.wrap.vr [[R1]], %valid : i16
|
|
# CHECK-NEXT: hw.output
|
|
# CHECK-NEXT: }
|
|
# CHECK-NEXT: esi.service.std.func @_FuncService
|
|
@unittestmodule(print=True)
|
|
class LoopbackCall(Module):
|
|
clk = Clock()
|
|
rst = Input(Bits(1))
|
|
|
|
metadata = Metadata(
|
|
name="LoopbackCall",
|
|
version="0.1",
|
|
)
|
|
|
|
@generator
|
|
def construct(self):
|
|
loopback_src = Wire(types.channel(types.i16))
|
|
loopback = loopback_src.buffer(self.clk, self.rst, 1, ChannelSignaling.FIFO)
|
|
args = esi.FuncService.get_call_chans(name=AppID("loopback"),
|
|
arg_type=Bits(24),
|
|
result=loopback)
|
|
|
|
ready = Wire(types.i1)
|
|
wide_data, valid = args.unwrap(ready)
|
|
data = wide_data[0:16]
|
|
data_chan, data_ready = loopback_src.type.wrap(data, valid)
|
|
ready.assign(data_ready)
|
|
loopback_src.assign(data_chan)
|
|
|
|
|
|
class Producer(Module):
|
|
clk = Clock()
|
|
int_out = OutputChannel(types.i32)
|
|
|
|
@generator
|
|
def construct(ports):
|
|
b, chans = TestFromBundle.pack()
|
|
HostComms.from_host(b, AppID("producer", 0))
|
|
ports.int_out = chans['ch1']
|
|
|
|
|
|
# TODO: fixme
|
|
# @unittestmodule(run_passes=True, print_after_passes=True, emit_outputs=True)
|
|
class PureTest(esi.PureModule):
|
|
|
|
@generator
|
|
def construct(ports):
|
|
clk = esi.PureModule.input_port("clk", ClockType())
|
|
rst = esi.PureModule.input_port("rst", Bits(1))
|
|
esi.Cosim(HostComms, clk, rst)
|
|
|
|
p2 = Producer(clk=clk, instance_name="prod2")
|
|
esi.PureModule.output_port("p2_int", p2.int_out)
|
|
esi.PureModule.param("FOO", Bits(5))
|
|
esi.PureModule.param("STR")
|
|
|
|
|
|
ExStruct = types.struct({
|
|
'a': Bits(4),
|
|
'b': UInt(32),
|
|
})
|
|
|
|
Bundle1 = Bundle([
|
|
BundledChannel("req", ChannelDirection.TO, types.channel(types.i32)),
|
|
BundledChannel("resp", ChannelDirection.FROM, types.channel(types.i1)),
|
|
])
|
|
# CHECK: Bundle<[('req', ChannelDirection.TO, Channel<Bits<32>, ValidReady>), ('resp', ChannelDirection.FROM, Channel<Bits<1>, ValidReady>)]>
|
|
print(Bundle1)
|
|
# CHECK: Channel<Bits<1>, ValidReady>
|
|
print(Bundle1.resp)
|
|
|
|
|
|
# CHECK-LABEL: hw.module @SendBundleTest(in %clk : !seq.clock, in %rst : i1, in %s1_in : !esi.channel<i32>, out b_send : !esi.bundle<[!esi.channel<i32> to "req", !esi.channel<i1> from "resp"]>, out i1_out : !esi.channel<i1>) attributes {output_file = #hw.output_file<"SendBundleTest.sv", includeReplicatedOps>} {
|
|
# CHECK-NEXT: [[B0:%.+]] = esi.buffer %clk, %rst, %s1_in {stages = 4 : i64} : !esi.channel<i32> -> !esi.channel<i32>
|
|
# CHECK-NEXT: %bundle, %resp = esi.bundle.pack [[B0]] : !esi.bundle<[!esi.channel<i32> to "req", !esi.channel<i1> from "resp"]>
|
|
# CHECK-NEXT: hw.output %bundle, %resp : !esi.bundle<[!esi.channel<i32> to "req", !esi.channel<i1> from "resp"]>, !esi.channel<i1>
|
|
@unittestmodule()
|
|
class SendBundleTest(Module):
|
|
clk = Clock()
|
|
rst = Reset()
|
|
b_send = SendBundle(Bundle1)
|
|
s1_in = InputChannel(types.i32)
|
|
i1_out = OutputChannel(types.i1)
|
|
|
|
@generator
|
|
def build(self):
|
|
s1_buffered = self.s1_in.buffer(self.clk, self.rst, 4)
|
|
self.b_send, from_chans = Bundle1.pack(req=s1_buffered)
|
|
self.i1_out = from_chans.resp
|
|
|
|
|
|
# CHECK-LABEL: hw.module @RecvBundleTest(in %b_recv : !esi.bundle<[!esi.channel<i32> to "req", !esi.channel<i1> from "resp"]>, in %i1_in : !esi.channel<i1>, out s1_out : !esi.channel<i32>) attributes {output_file = #hw.output_file<"RecvBundleTest.sv", includeReplicatedOps>} {
|
|
# CHECK-NEXT: %req = esi.bundle.unpack %i1_in from %b_recv : !esi.bundle<[!esi.channel<i32> to "req", !esi.channel<i1> from "resp"]>
|
|
# CHECK-NEXT: hw.output %req : !esi.channel<i32>
|
|
@unittestmodule()
|
|
class RecvBundleTest(Module):
|
|
b_recv = RecvBundle(Bundle1)
|
|
s1_out = OutputChannel(types.i32)
|
|
i1_in = InputChannel(types.i1)
|
|
|
|
@generator
|
|
def build(self):
|
|
to_channels = self.b_recv.unpack(resp=self.i1_in)
|
|
self.s1_out = to_channels['req']
|
|
|
|
|
|
# CHECK-LABEL: hw.module @ChannelTransform(in %s1_in : !esi.channel<i32>, out s2_out : !esi.channel<i8>)
|
|
# CHECK-NEXT: %valid, %ready, %data = esi.snoop.vr %s1_in : !esi.channel<i32>
|
|
# CHECK-NEXT: %rawOutput, %valid_0 = esi.unwrap.vr %s1_in, %ready_1 : i32
|
|
# CHECK-NEXT: [[R0:%.+]] = comb.extract %rawOutput from 0 : (i32) -> i8
|
|
# CHECK-NEXT: %chanOutput, %ready_1 = esi.wrap.vr [[R0]], %valid_0 : i8
|
|
# CHECK-NEXT: hw.output %chanOutput : !esi.channel<i8>
|
|
@unittestmodule()
|
|
class ChannelTransform(Module):
|
|
s1_in = InputChannel(Bits(32))
|
|
s2_out = OutputChannel(Bits(8))
|
|
|
|
@generator
|
|
def build(self):
|
|
valid, ready, data = self.s1_in.snoop()
|
|
self.s2_out = self.s1_in.transform(lambda x: x[0:8])
|
|
|
|
|
|
# CHECK-LABEL: hw.module @CoerceBundle(in %b_in : !esi.bundle<[!esi.channel<i8> from "resp", !esi.channel<i32> to "req"]>, out b_out : !esi.bundle<[!esi.channel<i8> from "result", !esi.channel<i32> to "arg"]>)
|
|
# CHECK-NEXT: %req = esi.bundle.unpack %result from %b_in : !esi.bundle<[!esi.channel<i8> from "resp", !esi.channel<i32> to "req"]>
|
|
# CHECK-NEXT: %bundle, %result = esi.bundle.pack %req : !esi.bundle<[!esi.channel<i8> from "result", !esi.channel<i32> to "arg"]>
|
|
# CHECK-NEXT: hw.output %bundle : !esi.bundle<[!esi.channel<i8> from "result", !esi.channel<i32> to "arg"]>
|
|
@unittestmodule()
|
|
class CoerceBundle(Module):
|
|
b_in = Input(
|
|
Bundle([
|
|
BundledChannel("resp", ChannelDirection.FROM, Channel(Bits(8))),
|
|
BundledChannel("req", ChannelDirection.TO, Channel(Bits(32))),
|
|
]))
|
|
b_out = Output(
|
|
Bundle([
|
|
BundledChannel("result", ChannelDirection.FROM, Channel(Bits(8))),
|
|
BundledChannel("arg", ChannelDirection.TO, Channel(Bits(32))),
|
|
]))
|
|
|
|
@generator
|
|
def build(ports):
|
|
ports.b_out = ports.b_in.coerce(CoerceBundle.b_out.type)
|
|
|
|
|
|
# CHECK-LABEL: hw.module @CoerceBundleTransform(in %b_in : !esi.bundle<[!esi.channel<i32> to "req", !esi.channel<i8> from "resp"]>, out b_out : !esi.bundle<[!esi.channel<i24> to "arg", !esi.channel<i16> from "result"]>)
|
|
# CHECK-NEXT: %rawOutput, %valid = esi.unwrap.vr %result, %ready : i16
|
|
# CHECK-NEXT: [[R0:%.+]] = comb.extract %rawOutput from 0 : (i16) -> i8
|
|
# CHECK-NEXT: %chanOutput, %ready = esi.wrap.vr [[R0]], %valid : i8
|
|
# CHECK-NEXT: %req = esi.bundle.unpack %chanOutput from %b_in : !esi.bundle<[!esi.channel<i32> to "req", !esi.channel<i8> from "resp"]>
|
|
# CHECK-NEXT: %rawOutput_0, %valid_1 = esi.unwrap.vr %req, %ready_3 : i32
|
|
# CHECK-NEXT: [[R1:%.+]] = comb.extract %rawOutput_0 from 0 : (i32) -> i24
|
|
# CHECK-NEXT: %chanOutput_2, %ready_3 = esi.wrap.vr [[R1]], %valid_1 : i24
|
|
# CHECK-NEXT: %bundle, %result = esi.bundle.pack %chanOutput_2 : !esi.bundle<[!esi.channel<i24> to "arg", !esi.channel<i16> from "result"]>
|
|
# CHECK-NEXT: hw.output %bundle : !esi.bundle<[!esi.channel<i24> to "arg", !esi.channel<i16> from "result"]>
|
|
@unittestmodule()
|
|
class CoerceBundleTransform(Module):
|
|
b_in = Input(
|
|
Bundle([
|
|
BundledChannel("req", ChannelDirection.TO, Channel(Bits(32))),
|
|
BundledChannel("resp", ChannelDirection.FROM, Channel(Bits(8))),
|
|
]))
|
|
b_out = Output(
|
|
Bundle([
|
|
BundledChannel("arg", ChannelDirection.TO, Channel(Bits(24))),
|
|
BundledChannel("result", ChannelDirection.FROM, Channel(Bits(16))),
|
|
]))
|
|
|
|
@generator
|
|
def build(ports):
|
|
ports.b_out = ports.b_in.coerce(CoerceBundleTransform.b_out.type,
|
|
lambda x: x[0:24], lambda x: x[0:8])
|
|
|
|
|
|
# CHECK-LABEL: hw.module @MMIOReq()
|
|
# CHECK-NEXT: %c0_i64 = hw.constant 0 : i64
|
|
# CHECK-NEXT: %false = hw.constant false
|
|
# CHECK-NEXT: [[B:%.+]] = esi.service.req <@MMIO::@read>(#esi.appid<"mmio_req">) : !esi.bundle<[!esi.channel<ui32> to "offset", !esi.channel<i64> from "data"]>
|
|
# CHECK-NEXT: %chanOutput, %ready = esi.wrap.vr %c0_i64, %false : i64
|
|
# CHECK-NEXT: %offset = esi.bundle.unpack %chanOutput from [[B]] : !esi.bundle<[!esi.channel<ui32> to "offset", !esi.channel<i64> from "data"]>
|
|
@unittestmodule(esi_sys=True)
|
|
class MMIOReq(Module):
|
|
|
|
@generator
|
|
def build(ports):
|
|
c64 = Bits(64)(0)
|
|
c1 = Bits(1)(0)
|
|
|
|
read_bundle = MMIO.read(AppID("mmio_req"))
|
|
|
|
data, _ = Channel(Bits(64)).wrap(c64, c1)
|
|
_ = read_bundle.unpack(data=data)
|
|
|
|
|
|
# CHECK-LABEL: hw.module @HostMemReq()
|
|
# CHECK-NEXT: [[R0:%.+]] = hwarith.constant 0 : ui64
|
|
# CHECK-NEXT: %false = hw.constant false
|
|
# CHECK-NEXT: [[R2:%.+]] = hwarith.constant 0 : ui8
|
|
# CHECK-NEXT: [[R3:%.+]] = hw.struct_create ([[R0]], [[R2]]) : !hw.struct<address: ui64, tag: ui8>
|
|
# CHECK-NEXT: %chanOutput, %ready = esi.wrap.vr [[R3]], %false : !hw.struct<address: ui64, tag: ui8>
|
|
# CHECK-NEXT: [[R1:%.+]] = esi.service.req <@_HostMem::@read>(#esi.appid<"host_mem_read_req">) : !esi.bundle<[!esi.channel<!hw.struct<address: ui64, tag: ui8>> from "req", !esi.channel<!hw.struct<tag: ui8, data: ui256>> to "resp"]>
|
|
# CHECK-NEXT: %resp = esi.bundle.unpack %chanOutput from [[R1]] : !esi.bundle<[!esi.channel<!hw.struct<address: ui64, tag: ui8>> from "req", !esi.channel<!hw.struct<tag: ui8, data: ui256>> to "resp"]>
|
|
# CHECK-NEXT: [[R4:%.+]] = hwarith.constant 0 : ui8
|
|
# CHECK-NEXT: [[R5:%.+]] = hwarith.constant 0 : ui256
|
|
# CHECK-NEXT: [[R6:%.+]] = hw.struct_create ([[R0]], [[R4]], [[R5]]) : !hw.struct<address: ui64, tag: ui8, data: ui256>
|
|
# CHECK-NEXT: %chanOutput_0, %ready_1 = esi.wrap.vr [[R6]], %false : !hw.struct<address: ui64, tag: ui8, data: ui256>
|
|
# CHECK-NEXT: [[R7:%.+]] = esi.service.req <@_HostMem::@write>(#esi.appid<"host_mem_write_req">) : !esi.bundle<[!esi.channel<!hw.struct<address: ui64, tag: ui8, data: ui256>> from "req", !esi.channel<ui8> to "ackTag"]>
|
|
# CHECK: esi.service.std.hostmem @_HostMem
|
|
@unittestmodule(esi_sys=True)
|
|
class HostMemReq(Module):
|
|
|
|
@generator
|
|
def build(ports):
|
|
u64 = UInt(64)(0)
|
|
c1 = Bits(1)(0)
|
|
|
|
read_address, _ = Channel(esi.HostMem.ReadReqType).wrap(
|
|
esi.HostMem.ReadReqType({
|
|
"tag": 0,
|
|
"address": u64
|
|
}), c1)
|
|
|
|
_ = HostMem.read(appid=AppID("host_mem_read_req"),
|
|
req=read_address,
|
|
data_type=UInt(256))
|
|
|
|
write_req, _ = esi.HostMem.wrap_write_req(tag=UInt(8)(0),
|
|
data=UInt(256)(0),
|
|
address=u64,
|
|
valid=c1)
|
|
_ = HostMem.write(appid=AppID("host_mem_write_req"), req=write_req)
|
|
|
|
|
|
def Writer(type):
|
|
|
|
class Writer(Module):
|
|
clk = Clock()
|
|
rst = Reset()
|
|
cmd = Input(type)
|
|
|
|
return Writer
|
|
|
|
|
|
# CHECK: hw.module @Ram1(in %clk : !seq.clock, in %rst : i1)
|
|
# CHECK: esi.service.instance #esi.appid<"ram"> svc @ram impl as "sv"(%clk, %rst) : (!seq.clock, i1) -> ()
|
|
# CHECK: [[WR:%.+]] = esi.service.req <@ram::@write>(#esi.appid<"ram_writer"[0]>) : !esi.bundle<[!esi.channel<!hw.struct<address: ui3, data: i32>> from "req", !esi.channel<i0> to "ack"]>
|
|
# CHECK: %rawOutput, %valid = esi.unwrap.vr %req, %ready : !hw.struct<address: ui3, data: ui32>
|
|
# CHECK: [[CASTED:%.+]] = hw.bitcast %rawOutput : (!hw.struct<address: ui3, data: ui32>) -> !hw.struct<address: ui3, data: i32>
|
|
# CHECK: %chanOutput, %ready = esi.wrap.vr [[CASTED]], %valid : !hw.struct<address: ui3, data: i32>
|
|
# CHECK: %ack = esi.bundle.unpack %chanOutput from [[WR]] : !esi.bundle<[!esi.channel<!hw.struct<address: ui3, data: i32>> from "req", !esi.channel<i0> to "ack"]>
|
|
# CHECK: %bundle, %req = esi.bundle.pack %ack : !esi.bundle<[!esi.channel<!hw.struct<address: ui3, data: ui32>> from "req", !esi.channel<i0> to "ack"]>
|
|
# CHECK: hw.instance "Writer" sym @Writer @Writer(clk: %clk: !seq.clock, rst: %rst: i1, cmd: %bundle: !esi.bundle<[!esi.channel<!hw.struct<address: ui3, data: ui32>> from "req", !esi.channel<i0> to "ack"]>) -> ()
|
|
|
|
|
|
@unittestmodule()
|
|
class Ram1(Module):
|
|
clk = Clock()
|
|
rst = Reset()
|
|
|
|
@generator
|
|
def build(ports):
|
|
ramsvc = esi.DeclareRandomAccessMemory(Bits(32), 8, "ram")
|
|
ramsvc.implement_as("sv", ports.clk, ports.rst)
|
|
|
|
mem_write = ramsvc.get_write(UInt(32))
|
|
Writer(mem_write.type)(clk=ports.clk, rst=ports.rst, cmd=mem_write)
|
|
|
|
|
|
# CHECK-LABEL: hw.module @UTurn(in %clk : !seq.clock, in %rst : i1, out out1 : !esi.bundle<[!esi.channel<i32> to "req", !esi.channel<i1> from "resp"]>, out out2 : !esi.bundle<[!esi.channel<i32> from "req", !esi.channel<i1> to "resp"]>)
|
|
# CHECK-NEXT: %bundle, %resp = esi.bundle.pack %req : !esi.bundle<[!esi.channel<i32> to "req", !esi.channel<i1> from "resp"]>
|
|
# CHECK-NEXT: %bundle_0, %req = esi.bundle.pack %resp : !esi.bundle<[!esi.channel<i32> from "req", !esi.channel<i1> to "resp"]>
|
|
# CHECK-NEXT: hw.output %bundle, %bundle_0 : !esi.bundle<[!esi.channel<i32> to "req", !esi.channel<i1> from "resp"]>, !esi.bundle<[!esi.channel<i32> from "req", !esi.channel<i1> to "resp"]>
|
|
@unittestmodule()
|
|
class UTurn(Module):
|
|
clk = Clock()
|
|
rst = Reset()
|
|
|
|
out1 = Output(Bundle1)
|
|
out2 = Output(Bundle1.inverted())
|
|
|
|
@generator
|
|
def build(ports):
|
|
ports.out1, ports.out2 = Bundle1.create_uturn()
|