16#include "mlir/IR/SymbolTable.h"
17#include "mlir/Pass/Pass.h"
18#include "mlir/Transforms/DialectConversion.h"
28 llvm::raw_string_ostream(typeID) << t;
29 return StringAttr::get(t.getContext(), typeID);
33 if (
auto ch = dyn_cast<ChannelType>(t))
35 if (
auto win = dyn_cast<WindowType>(t))
36 t = win.getLoweredType();
37 return hw::getBitWidth(t);
51 : ImplicitLocOpBuilder(UnknownLoc::get(top->getContext()), top),
52 a(StringAttr::get(getContext(),
"a")),
53 aValid(StringAttr::get(getContext(),
"a_valid")),
54 aReady(StringAttr::get(getContext(),
"a_ready")),
55 x(StringAttr::get(getContext(),
"x")),
56 xValid(StringAttr::get(getContext(),
"x_valid")),
57 xReady(StringAttr::get(getContext(),
"x_ready")),
58 dataOutValid(StringAttr::get(getContext(),
"DataOutValid")),
59 dataOutReady(StringAttr::get(getContext(),
"DataOutReady")),
60 dataOut(StringAttr::get(getContext(),
"DataOut")),
61 dataInValid(StringAttr::get(getContext(),
"DataInValid")),
62 dataInReady(StringAttr::get(getContext(),
"DataInReady")),
63 dataIn(StringAttr::get(getContext(),
"DataIn")),
64 clk(StringAttr::get(getContext(),
"clk")),
65 rst(StringAttr::get(getContext(),
"rst")),
66 width(StringAttr::get(getContext(),
"WIDTH")) {
68 auto regions = top->getRegions();
69 if (regions.empty()) {
70 top->emitError(
"ESI HW Builder needs a region to insert HW.");
72 auto ®ion = regions.front();
74 setInsertionPoint(®ion.front(), region.front().begin());
78 StringRef proposedNameRef) {
79 SmallString<64> proposedName = proposedNameRef;
82 for (
char &ch : proposedName) {
90 size_t baseLength = proposedName.size();
92 while (SymbolTable::lookupSymbolIn(tableOp, proposedName)) {
93 proposedName.resize(baseLength);
94 proposedName.append(llvm::utostr(++tries));
97 return StringAttr::get(tableOp->getContext(), proposedName);
102 getInsertionPoint()->getParentWithTrait<mlir::OpTrait::SymbolTable>();
105 std::string portTypeName;
106 llvm::raw_string_ostream nameOS(portTypeName);
107 TypeSwitch<Type>(port.getInner())
108 .Case([&](hw::ArrayType arr) {
109 nameOS <<
"ArrayOf" << arr.getNumElements() <<
'x'
110 << arr.getElementType();
112 .Case([&](hw::StructType t) { nameOS <<
"Struct"; })
113 .Default([&](Type t) { nameOS << port.getInner(); });
116 ssize_t i = portTypeName.size() - 1;
117 while (i >= 0 && portTypeName[i] ==
'_') {
120 portTypeName = portTypeName.substr(0, i + 1);
123 SmallString<64> proposedName(
"IValidReady_");
124 proposedName.append(portTypeName);
130 auto type = IntegerType::get(
width.getContext(), 32, IntegerType::Unsigned);
131 auto widthParam = ParamDeclAttr::get(
width.getContext(),
width, type, value);
132 return ArrayAttr::get(
width.getContext(), widthParam);
140 PipelineStageOp stage) {
141 Type dataType = stage.innerType();
152 llvm::SmallVector<PortInfo> ports = {
154 {{
rst, getI1Type(), ModulePort::Direction::Input}, argn++}};
156 ports.push_back({{
a, dataType, ModulePort::Direction::Input}, argn++});
158 {{
aValid, getI1Type(), ModulePort::Direction::Input}, argn++});
160 {{
aReady, getI1Type(), ModulePort::Direction::Output}, resn++});
161 ports.push_back({{
x, dataType, ModulePort::Direction::Output}, resn++});
164 {{
xValid, getI1Type(), ModulePort::Direction::Output}, resn++});
166 {{
xReady, getI1Type(), ModulePort::Direction::Input}, argn++});
168 stageMod = HWModuleExternOp::create(
182 SmallVector<Attribute, 8> params;
184 ParamDeclAttr::get(
"ENDPOINT_ID", NoneType::get(getContext())));
186 ParamDeclAttr::get(
"TO_HOST_TYPE_ID", NoneType::get(getContext())));
187 params.push_back(ParamDeclAttr::get(
"TO_HOST_SIZE_BITS", getI32Type()));
189 auto dataInType = hw::IntType::get(hw::ParamDeclRefAttr::get(
190 StringAttr::get(getContext(),
"TO_HOST_SIZE_BITS"),
191 getIntegerType(32,
false)));
194 {{
rst, getI1Type(), ModulePort::Direction::Input}, 1},
195 {{
dataInValid, getI1Type(), ModulePort::Direction::Input}, 2},
196 {{
dataInReady, getI1Type(), ModulePort::Direction::Output}, 3},
197 {{
dataIn, dataInType, ModulePort::Direction::Input}, 4}};
201 "Cosim_Endpoint_ToHost", ArrayAttr::get(getContext(), params));
210 SmallVector<Attribute, 8> params;
212 ParamDeclAttr::get(
"ENDPOINT_ID", NoneType::get(getContext())));
214 ParamDeclAttr::get(
"FROM_HOST_TYPE_ID", NoneType::get(getContext())));
215 params.push_back(ParamDeclAttr::get(
"FROM_HOST_SIZE_BITS", getI32Type()));
217 auto dataInType = hw::IntType::get(hw::ParamDeclRefAttr::get(
218 StringAttr::get(getContext(),
"FROM_HOST_SIZE_BITS"),
219 getIntegerType(32,
false)));
222 {{
rst, getI1Type(), ModulePort::Direction::Input}, 1},
223 {{
dataOutValid, getI1Type(), ModulePort::Direction::Output}, 2},
224 {{
dataOutReady, getI1Type(), ModulePort::Direction::Input}, 3},
225 {{
dataOut, dataInType, ModulePort::Direction::Output}, 4}};
229 "Cosim_Endpoint_FromHost", ArrayAttr::get(getContext(), params));
239 return ifaceIter->second;
246 return InterfaceOp::create(
248 InterfaceSignalOp::create(*
this,
validStr, getI1Type());
249 InterfaceSignalOp::create(*
this,
readyStr, getI1Type());
250 InterfaceSignalOp::create(*
this,
dataStr, chan.getInner());
251 llvm::SmallVector<StringRef> validDataStrs;
253 validDataStrs.push_back(
dataStr);
254 InterfaceModportOp::create(*
this,
sinkStr,
257 InterfaceModportOp::create(*
this,
sourceStr,
static void registerPasses()
static StringAttr constructUniqueSymbol(Operation *tableOp, StringRef proposedNameRef)
const StringAttr dataOutValid
hw::HWModuleExternOp declareCosimEndpointFromHostModule(Operation *symTable)
static constexpr char validStr[]
const StringAttr dataInValid
const StringAttr dataOutReady
static constexpr char sinkStr[]
std::optional< hw::HWModuleExternOp > declaredCosimEndpointToHostModule
llvm::DenseMap< Type, sv::InterfaceOp > portTypeLookup
static constexpr char readyStr[]
hw::HWModuleExternOp declareCosimEndpointToHostModule(Operation *symTable)
Write an 'ExternModuleOp' to use a hand-coded SystemVerilog module.
static constexpr char dataStr[]
StringAttr constructInterfaceName(ChannelType)
Construct a type-appropriate name for the interface, making sure it's not taken in the symbol table.
sv::InterfaceOp constructInterface(ChannelType)
ESIHWBuilder(Operation *top)
sv::InterfaceOp getOrConstructInterface(ChannelType)
Return the InterfaceType which corresponds to an ESI port type.
std::optional< hw::HWModuleExternOp > declaredCosimEndpointFromHostModule
llvm::DenseMap< Type, hw::HWModuleExternOp > declaredStage
static constexpr char sourceStr[]
hw::HWModuleExternOp declareStage(Operation *symTable, PipelineStageOp)
Write an 'ExternModuleOp' to use a hand-coded SystemVerilog module.
const StringAttr dataInReady
ArrayAttr getStageParameterList(Attribute value)
Return a parameter list for the stage module with the specified value.
uint64_t getWidth(Type t)
StringAttr getTypeID(Type t)
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
This holds the name, type, direction of a module's ports.