CIRCT  20.0.0git
circt_tcl.cpp
Go to the documentation of this file.
1 #include <stdlib.h>
2 #include <tcl.h>
3 
8 #include "mlir/CAPI/IR.h"
9 #include "mlir/Parser/Parser.h"
10 #include "mlir/Support/FileUtilities.h"
11 #include "llvm/Support/SourceMgr.h"
12 
13 static int operationTypeSetFromAnyProc(Tcl_Interp *interp, Tcl_Obj *obj) {
14  return TCL_ERROR;
15 }
16 
17 static void operationTypeUpdateStringProc(Tcl_Obj *obj) {
18  std::string str;
19  auto *op = unwrap(MlirOperation{obj->internalRep.otherValuePtr});
20  llvm::raw_string_ostream stream(str);
21  op->print(stream);
22  obj->length = str.length();
23  obj->bytes = Tcl_Alloc(obj->length);
24  memcpy(obj->bytes, str.c_str(), obj->length);
25  obj->bytes[obj->length] = '\0';
26 }
27 
28 static void operationTypeDupIntRepProc(Tcl_Obj *src, Tcl_Obj *dup) {
29  auto *op = unwrap(MlirOperation{src->internalRep.otherValuePtr})->clone();
30  dup->internalRep.otherValuePtr = wrap(op).ptr;
31 }
32 
33 static void operationTypeFreeIntRepProc(Tcl_Obj *obj) {
34  auto *op = unwrap(MlirOperation{obj->internalRep.otherValuePtr});
35  op->erase();
36 }
37 
38 static int returnErrorStr(Tcl_Interp *interp, const char *error) {
39  Tcl_SetObjResult(interp, Tcl_NewStringObj(error, -1));
40  return TCL_ERROR;
41 }
42 
43 static int loadFirMlirFile(mlir::MLIRContext *context, Tcl_Interp *interp,
44  int objc, Tcl_Obj *const objv[]) {
45  if (objc != 3) {
46  Tcl_WrongNumArgs(interp, objc, objv, "usage: circt load [MLIR|FIR] [file]");
47  return TCL_ERROR;
48  }
49 
50  std::string errorMessage;
51  auto input = mlir::openInputFile(llvm::StringRef(Tcl_GetString(objv[2])),
52  &errorMessage);
53 
54  if (!input)
55  return returnErrorStr(interp, errorMessage.c_str());
56 
57  llvm::SourceMgr sourceMgr;
58  sourceMgr.AddNewSourceBuffer(std::move(input), llvm::SMLoc());
59  mlir::SourceMgrDiagnosticHandler sourceMgrHandler(sourceMgr, context);
60 
61  MlirOperation module;
62  if (!strcmp(Tcl_GetString(objv[1]), "MLIR"))
63  module = wrap(mlir::parseSourceFile<mlir::ModuleOp>(sourceMgr, context)
64  .release()
65  .getOperation());
66  else if (!strcmp(Tcl_GetString(objv[1]), "FIR"))
67  // TODO
68  return returnErrorStr(interp, "loading FIR files is unimplemented :(");
69  else
70  return TCL_ERROR;
71 
72  if (mlirOperationIsNull(module))
73  return returnErrorStr(interp, "error loading module");
74 
75  auto *m = module.ptr;
76 
77  auto *obj = Tcl_NewObj();
78  obj->typePtr = Tcl_GetObjType("MlirOperation");
79  obj->internalRep.otherValuePtr = (void *)m;
80  obj->length = 0;
81  obj->bytes = nullptr;
82  Tcl_SetObjResult(interp, obj);
83 
84  return TCL_OK;
85 }
86 
87 static int circtTclFunction(ClientData cdata, Tcl_Interp *interp, int objc,
88  Tcl_Obj *const objv[]) {
89  if (objc < 2) {
90  Tcl_WrongNumArgs(interp, objc, objv, "usage: circt load");
91  return TCL_ERROR;
92  }
93 
94  auto *context = (mlir::MLIRContext *)cdata;
95 
96  if (!strcmp("load", Tcl_GetString(objv[1])))
97  return loadFirMlirFile(context, interp, objc - 1, objv + 1);
98 
99  return returnErrorStr(interp, "usage: circt load");
100 }
101 
102 static void deleteContext(ClientData data) { delete (mlir::MLIRContext *)data; }
103 
104 extern "C" {
105 
106 int DLLEXPORT Circt_Init(Tcl_Interp *interp) {
107  if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL)
108  return TCL_ERROR;
109 
110  // Register types
111  Tcl_ObjType *operationType = new Tcl_ObjType;
112  operationType->name = "MlirOperation";
113  operationType->setFromAnyProc = operationTypeSetFromAnyProc;
114  operationType->updateStringProc = operationTypeUpdateStringProc;
115  operationType->dupIntRepProc = operationTypeDupIntRepProc;
116  operationType->freeIntRepProc = operationTypeFreeIntRepProc;
117  Tcl_RegisterObjType(operationType);
118 
119  // Register package
120  if (Tcl_PkgProvide(interp, "Circt", "1.0") == TCL_ERROR)
121  return TCL_ERROR;
122 
123  // Register commands
124  auto *context = new mlir::MLIRContext;
125  context->loadDialect<circt::hw::HWDialect, circt::comb::CombDialect,
126  circt::sv::SVDialect>();
127  Tcl_CreateObjCommand(interp, "circt", circtTclFunction, context,
128  deleteContext);
129  return TCL_OK;
130 }
131 }
return wrap(CMemoryType::get(unwrap(ctx), baseType, numElements))
static EvaluatorValuePtr unwrap(OMEvaluatorValue c)
Definition: OM.cpp:113
static int returnErrorStr(Tcl_Interp *interp, const char *error)
Definition: circt_tcl.cpp:38
static void operationTypeUpdateStringProc(Tcl_Obj *obj)
Definition: circt_tcl.cpp:17
static int circtTclFunction(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
Definition: circt_tcl.cpp:87
int DLLEXPORT Circt_Init(Tcl_Interp *interp)
Definition: circt_tcl.cpp:106
static int loadFirMlirFile(mlir::MLIRContext *context, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
Definition: circt_tcl.cpp:43
static int operationTypeSetFromAnyProc(Tcl_Interp *interp, Tcl_Obj *obj)
Definition: circt_tcl.cpp:13
static void operationTypeFreeIntRepProc(Tcl_Obj *obj)
Definition: circt_tcl.cpp:33
static void deleteContext(ClientData data)
Definition: circt_tcl.cpp:102
static void operationTypeDupIntRepProc(Tcl_Obj *src, Tcl_Obj *dup)
Definition: circt_tcl.cpp:28