Skip to content
Open
Show file tree
Hide file tree
Changes from 5 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
5 changes: 5 additions & 0 deletions python/heterocl/compute_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,11 @@ def compute_body(name,
index, _, _ = get_index(shape, indices, 0)
stage.emit(_make.Store(buffer_var, _make.Cast(dtype, ret), index))
stmt = make_for(indices, stage.pop_stmt(), 0, name)
elif isinstance(ret, str):
indices = lambda_ivs
index, _, _ = get_index(shape, indices, 0)
stage.emit(_make.Store(buffer_var, _make.CastStr(dtype, ret), index))
stmt = make_for(indices, stage.pop_stmt(), 0, name)
elif isinstance(ret, Tensor): # reduction
ret_ivs = [_IterVar((0, ret.shape[i]), ret.name+"_i" + str(i), 0)
for i in range(0, len(ret.shape))]
Expand Down
167 changes: 167 additions & 0 deletions tests/test_scalar.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
import heterocl as hcl
import numpy as np
hcl.init()

def test_int7(A):
def doit(x):
x = 0xFA_FF00_FFFF
v = hcl.scalar("0x4A", "v", dtype=hcl.Int(7))
return v.v
return hcl.compute(A.shape, lambda i: doit(i), "doit", dtype=hcl.Int(7))

def test_uint7(A):
def doit(x):
x = 0xFA_FF00_FFFF
v = hcl.scalar("0x4A", "v", dtype=hcl.UInt(7))
return v.v
return hcl.compute(A.shape, lambda i: doit(i), "doit", dtype=hcl.UInt(7))

def test_int15(A):
def doit(x):
x = 0xFA_FF00_FFFF
v = hcl.scalar("0x40FF", "v", dtype=hcl.Int(15))
return v.v
return hcl.compute(A.shape, lambda i: doit(i), "doit", dtype=hcl.Int(15))

def test_uint15(A):
def doit(x):
x = 0xFA_FF00_FFFF
v = hcl.scalar("0x40FF", "v", dtype=hcl.UInt(15))
return v.v
return hcl.compute(A.shape, lambda i: doit(i), "doit", dtype=hcl.UInt(15))

def test_int31(A):
def doit(x):
x = 0xFA_FF00_FFFF
v = hcl.scalar("0x4F0000FF", "v", dtype=hcl.Int(31))
return v.v
return hcl.compute(A.shape, lambda i: doit(i), "doit", dtype=hcl.Int(31))

def test_uint31(A):
def doit(x):
x = 0xFA_FF00_FFFF
v = hcl.scalar("0x4F0000FF", "v", dtype=hcl.UInt(31))
return v.v
return hcl.compute(A.shape, lambda i: doit(i), "doit", dtype=hcl.UInt(31))

def test_int62(A):
def doit(x):
x = 0xFA_FF00_FFFF
v = hcl.scalar("0x2A000000FF0000FF", "v", dtype=hcl.Int(62))
return v.v
return hcl.compute(A.shape, lambda i: doit(i), "doit", dtype=hcl.Int(62))

def test_uint62(A):
def doit(x):
x = 0xFA_FF00_FFFF
v = hcl.scalar("0x2A000000FF0000FF", "v", dtype=hcl.UInt(62))
return v.v
return hcl.compute(A.shape, lambda i: doit(i), "doit", dtype=hcl.UInt(62))

A_int7 = hcl.placeholder((1,), "A_int7", dtype=hcl.Int(7))
s_int7 = hcl.create_schedule([A_int7], test_int7)
m_int7 = hcl.build (s_int7)

A_uint7 = hcl.placeholder((1,), "A_uint7", dtype=hcl.UInt(7))
s_uint7 = hcl.create_schedule([A_uint7], test_uint7)
m_uint7 = hcl.build (s_uint7)

A_int15 = hcl.placeholder((1,), "A_int15", dtype=hcl.Int(15))
s_int15 = hcl.create_schedule([A_int15], test_int15)
m_int15 = hcl.build (s_int15)

A_uint15 = hcl.placeholder((1,), "A_uint15", dtype=hcl.UInt(15))
s_uint15 = hcl.create_schedule([A_uint15], test_uint15)
m_uint15 = hcl.build (s_uint15)

A_int31 = hcl.placeholder((1,), "A_int31", dtype=hcl.Int(31))
s_int31 = hcl.create_schedule([A_int31], test_int31)
m_int31 = hcl.build (s_int31)

A_uint31 = hcl.placeholder((1,), "A_uint31", dtype=hcl.UInt(31))
s_uint31 = hcl.create_schedule([A_uint31], test_uint31)
m_uint31 = hcl.build (s_uint31)

A_int62 = hcl.placeholder((1,), "A_int62", dtype=hcl.Int(62))
s_int62 = hcl.create_schedule([A_int62], test_int62)
m_int62 = hcl.build (s_int62)

A_uint62 = hcl.placeholder((1,), "A_uint62", dtype=hcl.UInt(62))
s_uint62 = hcl.create_schedule([A_uint62], test_uint62)
m_uint62 = hcl.build (s_uint62)

A_int7 = hcl.asarray([0xA0A0], dtype=A_int7.dtype)
R_int7 = hcl.asarray([99], dtype=hcl.Int(7))
m_int7(A_int7, R_int7)

A_uint7 = hcl.asarray([0xA0A0], dtype=A_uint7.dtype)
R_uint7 = hcl.asarray([99], dtype=hcl.UInt(7))
m_uint7(A_uint7, R_uint7)

A_int15 = hcl.asarray([0xA0A0], dtype=A_int15.dtype)
R_int15 = hcl.asarray([99], dtype=hcl.Int(15))
m_int15(A_int15, R_int15)

A_uint15 = hcl.asarray([0xA0A0], dtype=A_uint15.dtype)
R_uint15 = hcl.asarray([99], dtype=hcl.UInt(15))
m_uint15(A_uint15, R_uint15)

A_int31 = hcl.asarray([0xA0A0], dtype=A_int31.dtype)
R_int31 = hcl.asarray([99], dtype=hcl.Int(31))
m_int31(A_int31, R_int31)

A_uint31 = hcl.asarray([0xA0A0], dtype=A_uint31.dtype)
R_uint31 = hcl.asarray([99], dtype=hcl.UInt(31))
m_uint31(A_uint31, R_uint31)

A_int62 = hcl.asarray([0xA0A0], dtype=A_int62.dtype)
R_int62 = hcl.asarray([99], dtype=hcl.Int(62))
m_int62(A_int62, R_int62)

A_uint62 = hcl.asarray([0xA0A0], dtype=A_uint62.dtype)
R_uint62 = hcl.asarray([99], dtype=hcl.UInt(62))
m_uint62(A_uint62, R_uint62)

print(f"R_int7 = {[bin(i) for i in R_int7.asnumpy()]}")
print(f"R_uint7 = {[hex(i) for i in R_uint7.asnumpy()]}")
print(f"R_int15 = {[hex(i) for i in R_int15.asnumpy()]}")
print(f"R_uint15 = {[hex(i) for i in R_uint15.asnumpy()]}")
print(f"R_int31 = {[hex(i) for i in R_int31.asnumpy()]}")
print(f"R_uint31 = {[hex(i) for i in R_uint31.asnumpy()]}")
print(f"R_int62 = {[hex(i) for i in R_int62.asnumpy()]}")
print(f"R_uint62 = {[hex(i) for i in R_uint62.asnumpy()]}")

def test_int127_lower(A):
def doit(x):
x = 0xFA_FF00_FFFF
v = hcl.scalar("0x8ABCFFFFFFBAFFFA000A", "v", dtype=hcl.UInt(127))
b = hcl.scalar(v >> 64, "b", dtype=hcl.UInt(63))
c = hcl.scalar(v & 0xFFFFFFFFFFFFFFFF, "c", dtype=hcl.UInt(64))
return c.v
return hcl.compute(A.shape, lambda i: doit(i), "doit", dtype=hcl.UInt(64))

def test_int127_upper(A):
def doit(x):
x = 0xFA_FF00_FFFF
v = hcl.scalar("0x8ABCFFFFFFBAFFFA000A", "v", dtype=hcl.UInt(127))
b = hcl.scalar(v >> 64, "b", dtype=hcl.UInt(63))
c = hcl.scalar(v & 0x7FFFFFFFFFFFFFFF, "c", dtype=hcl.UInt(64))
return b.v
return hcl.compute(A.shape, lambda i: doit(i), "doit", dtype=hcl.UInt(63))

A = hcl.placeholder((1,), "A", dtype=hcl.UInt(63))
s_lower = hcl.create_schedule([A], test_int127_lower)
s_upper = hcl.create_schedule([A], test_int127_upper)
m_lower = hcl.build(s_lower)
m_upper = hcl.build(s_upper)

hcl_A = hcl.asarray([0], hcl.UInt(63))
hcl_R_lower = hcl.asarray([0], hcl.UInt(64))
hcl_R_upper = hcl.asarray([0], hcl.UInt(63))

m_lower(hcl_A, hcl_R_lower)
m_upper(hcl_A, hcl_R_upper)

print(f"hcl_R_lower = {[hex(i) for i in hcl_R_lower.asnumpy()]}")
print(f"hcl_R_upper = {[hex(i) for i in hcl_R_upper.asnumpy()]}")

1 change: 1 addition & 0 deletions tvm/HalideIR/src/ir/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ enum class IRNodeType : int {
FloatImm,
StringImm,
Cast,
CastStr,
Variable,
Add,
Sub,
Expand Down
11 changes: 11 additions & 0 deletions tvm/HalideIR/src/ir/IR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,13 @@ Expr Cast::make(Type t, Expr v) {
return Expr(node);
}

Expr CastStr::make(Type t, const std::string &val) {
std::shared_ptr<CastStr> node = std::make_shared<CastStr>();
node->type = t;
node->value = val;
return Expr(node);
}

Expr And::make(Expr a, Expr b) {
internal_assert(a.defined()) << "And of undefined\n";
internal_assert(b.defined()) << "And of undefined\n";
Expand Down Expand Up @@ -1050,6 +1057,10 @@ void ExprNode<Cast>::accept(IRVisitor *v, const Expr &e) const {
v->visit((const Cast *)this, e);
}
template <>
void ExprNode<CastStr>::accept(IRVisitor *v, const Expr &e) const {
v->visit((const CastStr *)this, e);
}
template <>
void ExprNode<Variable>::accept(IRVisitor *v, const Expr &e) const {
v->visit((const Variable *)this, e);
}
Expand Down
13 changes: 13 additions & 0 deletions tvm/HalideIR/src/ir/IR.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,19 @@ struct Cast : public ExprNode<Cast> {
static constexpr const char *_type_key = "Cast";
};

/** Cast a node from string to other datatype. */
struct CastStr : public ExprNode<CastStr> {
std::string value;
EXPORT static Expr make(Type t, const std::string &val);
void VisitAttrs(IR::AttrVisitor *v) final {
v->Visit("dtype", &type);
v->Visit("value", &value);
}
static const IRNodeType _type_info = IRNodeType::CastStr;
static constexpr const char *_type_key = "CastStr";
};


/** base class of all Binary arithematic ops */
template <typename T>
struct BinaryOpNode : public ExprNode<T> {
Expand Down
5 changes: 5 additions & 0 deletions tvm/HalideIR/src/ir/IREquality.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class IRComparer : public IRVisitor {
void visit(const FloatImm *, const Expr &);
void visit(const StringImm *, const Expr &);
void visit(const Cast *, const Expr &);
void visit(const CastStr *, const Expr &);
void visit(const Variable *, const Expr &);
void visit(const Add *, const Expr &);
void visit(const Sub *, const Expr &);
Expand Down Expand Up @@ -293,6 +294,10 @@ void IRComparer::visit(const StringImm *op, const Expr &e) {
compare_names(node->value, op->value);
}

void IRComparer::visit(const CastStr *op, const Expr &e) {
const CastStr *node = expr_.as<CastStr>();
compare_names(node->value, op->value);
}
void IRComparer::visit(const Cast *op, const Expr &e) {
compare_expr(expr_.as<Cast>()->value, op->value);
}
Expand Down
9 changes: 9 additions & 0 deletions tvm/HalideIR/src/ir/IRMutator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,15 @@ void IRMutator::visit(const Cast *op, const Expr &e) {
}
}

void IRMutator::visit(const CastStr *op, const Expr &e) {
std::string value = op->value;
if (value == op->value) {
expr = e;
} else {
expr = CastStr::make(op->type, value);
}
}

// use macro to access private function.
#define MUTATE_BINARY_OP(op, e, T) \
Expr a = mutate(op->a); \
Expand Down
1 change: 1 addition & 0 deletions tvm/HalideIR/src/ir/IRMutator.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class IRMutator : public IRVisitor {
EXPORT virtual void visit(const FloatImm *, const Expr &);
EXPORT virtual void visit(const StringImm *, const Expr &);
EXPORT virtual void visit(const Cast *, const Expr &);
EXPORT virtual void visit(const CastStr *, const Expr &);
EXPORT virtual void visit(const Variable *, const Expr &);
EXPORT virtual void visit(const Add *, const Expr &);
EXPORT virtual void visit(const Sub *, const Expr &);
Expand Down
35 changes: 35 additions & 0 deletions tvm/HalideIR/src/ir/IRPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,41 @@ TVM_STATIC_IR_FUNCTOR(IRPrinter, vtable)
p->print(op->value);
p->stream << ')';
})
.set_dispatch<CastStr>([](const CastStr *op, IRPrinter *p) {
p->stream << op->type << '(';
auto &stream = p->stream;
stream << '"';
for (size_t i = 0; i < op->value.size(); i++) {
unsigned char c = op->value[i];
if (c >= ' ' && c <= '~' && c != '\\' && c != '"') {
stream << c;
} else {
stream << '\\';
switch (c) {
case '"':
stream << '"';
break;
case '\\':
stream << '\\';
break;
case '\t':
stream << 't';
break;
case '\r':
stream << 'r';
break;
case '\n':
stream << 'n';
break;
default:
string hex_digits = "0123456789ABCDEF";
stream << 'x' << hex_digits[c >> 4] << hex_digits[c & 0xf];
}
}
}
stream << '"';
p->stream << ')';
})
.set_dispatch<Variable>([](const Variable *op, IRPrinter *p) {
// omit the type
// stream << op->name << "." << op->type;
Expand Down
3 changes: 3 additions & 0 deletions tvm/HalideIR/src/ir/IRVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ void IRVisitor::visit(const FloatImm *, const Expr &) {}
void IRVisitor::visit(const StringImm *, const Expr &) {}

void IRVisitor::visit(const Cast *op, const Expr &) { op->value.accept(this); }
void IRVisitor::visit(const CastStr *op, const Expr &) { }

void IRVisitor::visit(const Variable *, const Expr &) {}

Expand Down Expand Up @@ -356,6 +357,8 @@ void IRGraphVisitor::visit(const StringImm *, const Expr &) {}

void IRGraphVisitor::visit(const Cast *op, const Expr &) { include(op->value); }

void IRGraphVisitor::visit(const CastStr *op, const Expr &) { }

void IRGraphVisitor::visit(const Variable *op, const Expr &) {}

void IRGraphVisitor::visit(const Add *op, const Expr &) {
Expand Down
2 changes: 2 additions & 0 deletions tvm/HalideIR/src/ir/IRVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class IRVisitor {
EXPORT virtual void visit(const FloatImm *, const Expr &);
EXPORT virtual void visit(const StringImm *, const Expr &);
EXPORT virtual void visit(const Cast *, const Expr &);
EXPORT virtual void visit(const CastStr *, const Expr &);
EXPORT virtual void visit(const Variable *, const Expr &);
EXPORT virtual void visit(const Add *, const Expr &);
EXPORT virtual void visit(const Sub *, const Expr &);
Expand Down Expand Up @@ -116,6 +117,7 @@ class IRGraphVisitor : public IRVisitor {
EXPORT virtual void visit(const FloatImm *, const Expr &);
EXPORT virtual void visit(const StringImm *, const Expr &);
EXPORT virtual void visit(const Cast *, const Expr &);
EXPORT virtual void visit(const CastStr *, const Expr &);
EXPORT virtual void visit(const Variable *, const Expr &);
EXPORT virtual void visit(const Add *, const Expr &);
EXPORT virtual void visit(const Sub *, const Expr &);
Expand Down
1 change: 1 addition & 0 deletions tvm/include/tvm/ir.h
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,7 @@ using Halide::Internal::Break;
using Halide::Internal::Broadcast;
using Halide::Internal::Call;
using Halide::Internal::Cast;
using Halide::Internal::CastStr;
using Halide::Internal::Div;
using Halide::Internal::EQ;
using Halide::Internal::Evaluate;
Expand Down
2 changes: 2 additions & 0 deletions tvm/include/tvm/ir_functor_ext.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ class ExprFunctor<R(const Expr& n, Args...)> {
virtual R VisitExpr_(const Or* op, Args... args) EXPR_FUNCTOR_DEFAULT;
virtual R VisitExpr_(const Reduce* op, Args... args) EXPR_FUNCTOR_DEFAULT;
virtual R VisitExpr_(const Cast* op, Args... args) EXPR_FUNCTOR_DEFAULT;
virtual R VisitExpr_(const CastStr* op, Args... args) EXPR_FUNCTOR_DEFAULT;
virtual R VisitExpr_(const Not* op, Args... args) EXPR_FUNCTOR_DEFAULT;
virtual R VisitExpr_(const Select* op, Args... args) EXPR_FUNCTOR_DEFAULT;
virtual R VisitExpr_(const Ramp* op, Args... args) EXPR_FUNCTOR_DEFAULT;
Expand Down Expand Up @@ -179,6 +180,7 @@ class ExprFunctor<R(const Expr& n, Args...)> {
IR_EXPR_FUNCTOR_DISPATCH(Or);
IR_EXPR_FUNCTOR_DISPATCH(Reduce);
IR_EXPR_FUNCTOR_DISPATCH(Cast);
IR_EXPR_FUNCTOR_DISPATCH(CastStr);
IR_EXPR_FUNCTOR_DISPATCH(Not);
IR_EXPR_FUNCTOR_DISPATCH(Select);
IR_EXPR_FUNCTOR_DISPATCH(Ramp);
Expand Down
1 change: 1 addition & 0 deletions tvm/include/tvm/ir_mutator.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ class TVM_DLL IRMutator {
virtual Expr Mutate_(const Or* op, const Expr& e);
virtual Expr Mutate_(const Reduce* op, const Expr& e);
virtual Expr Mutate_(const Cast* op, const Expr& e);
virtual Expr Mutate_(const CastStr* op, const Expr& e);
virtual Expr Mutate_(const Not* op, const Expr& e);
virtual Expr Mutate_(const Select* op, const Expr& e);
virtual Expr Mutate_(const Ramp* op, const Expr& e);
Expand Down
1 change: 1 addition & 0 deletions tvm/include/tvm/ir_visitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ class TVM_DLL IRVisitor {
virtual void Visit_(const Or* op);
virtual void Visit_(const Reduce* op);
virtual void Visit_(const Cast* op);
virtual void Visit_(const CastStr* op);
virtual void Visit_(const Not* op);
virtual void Visit_(const Select* op);
virtual void Visit_(const Ramp* op);
Expand Down
1 change: 1 addition & 0 deletions tvm/src/api/api_ir.cc
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ REGISTER_MAKE_BINARY_OP(Or);
REGISTER_MAKE1(Not);
REGISTER_MAKE3(Ramp);
REGISTER_MAKE2(Cast);
REGISTER_MAKE2(CastStr);
REGISTER_MAKE2(Broadcast);
REGISTER_MAKE3(Let);
REGISTER_MAKE3(LetStmt);
Expand Down
Loading