Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
3 changes: 2 additions & 1 deletion include/NeuraDialect/NeuraOps.td
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// NeuraOps.td - Custom operation definitions.

include "NeuraDialect/NeuraDialect.td"
include "mlir/IR/BuiltinTypes.td"

// ----------------------------------------------------
// Defines basic scalar operations.
Expand Down Expand Up @@ -39,7 +40,7 @@ def Neura_FAddOp : Op<NeuraDialect, "fadd"> {
let arguments = (ins AnyType:$lhs, AnyType:$rhs, Optional<AnyType>:$predicate);
let results = (outs AnyType:$result);
// let assemblyFormat = "$lhs `,` $rhs `,` $predicate attr-dict `:` type($result)";
//let traits = [SameOperandsAndResultElementType];
// let traits = [SameOperandsAndResultElementType];
}

// Defines a floating-point substraction operation.
Expand Down
18 changes: 18 additions & 0 deletions test/lit.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import os
import lit.formats

config.name = 'Neura Dialect Tests'
config.test_format = lit.formats.ShTest(True)
config.suffixes = ['.mlir']
config.test_source_root = os.path.dirname(__file__)
config.test_exec_root = os.path.dirname(__file__)
config.excludes = ['samples']

# Tool substitutions from CMake
config.substitutions.append(('mlir-neura-opt', '/home/item/dataflow/build/tools/mlir-neura-opt/mlir-neura-opt'))
config.substitutions.append(('neura-interpreter', '/home/item/dataflow/build/tools/neura-interpreter/neura-interpreter'))
config.substitutions.append(('neura-compiler', '/home/item/dataflow/build/tools/neura-compiler/neura-compiler'))
config.substitutions.append(('FileCheck', '/home/item/llvm-project/build/./bin/FileCheck'))
config.substitutions.append(('mlir-opt', '/home/item/llvm-project/build/./bin/mlir-opt'))
config.substitutions.append(('mlir-translate', '/home/item/llvm-project/build/./bin/mlir-translate'))
config.substitutions.append(('llc', '/home/item/llvm-project/build/./bin/llc'))
68 changes: 58 additions & 10 deletions test/neura/interpreter/add.mlir
Original file line number Diff line number Diff line change
@@ -1,13 +1,61 @@
// RUN: neura-interpreter %s | FileCheck %s

module {
func.func @test() -> f32 {
%arg0 = "neura.constant"() <{value = 9.0 : f32}> : () -> f32
%cst = "neura.constant"() <{value = 2.0 : f32}> : () -> f32
%0 = "neura.data_mov"(%arg0) : (f32) -> f32
%1 = "neura.data_mov"(%cst) : (f32) -> f32
%2 = "neura.fadd"(%0, %1) : (f32, f32) -> f32
return %2 : f32
// CHECK: 11.0
}
// ===----------------------------------------------------------------------===//
// Test 1: Add two float constants
// ===----------------------------------------------------------------------===//
func.func @test_add_f32() -> f32 {
%a = arith.constant 10.0 : f32
%b = arith.constant 32.0 : f32
%res = "neura.add"(%a, %b) : (f32, f32) -> f32
// CHECK: [neura-interpreter] Executing neura.add:
// CHECK-NEXT: LHS: value = 1.000000e+01, predicate = 1
// CHECK-NEXT: RHS: value = 3.200000e+01, predicate = 1
// CHECK-NEXT: Result: value = 4.200000e+01, predicate = 1
// CHECK-NEXT: [neura-interpreter] Output: 42.000000
return %res : f32
}

// ===----------------------------------------------------------------------===//
// Test 2: Add a negative and positive float
// ===----------------------------------------------------------------------===//
func.func @test_add_negative() -> f32 {
%a = arith.constant -5.0 : f32
%b = arith.constant 3.0 : f32
%res = "neura.add"(%a, %b) : (f32, f32) -> f32
// CHECK: [neura-interpreter] Executing neura.add:
// CHECK-NEXT: LHS: value = -5.000000e+00, predicate = 1
// CHECK-NEXT: RHS: value = 3.000000e+00, predicate = 1
// CHECK-NEXT: Result: value = -2.000000e+00, predicate = 1
// CHECK-NEXT: [neura-interpreter] Output: -2.000000
return %res : f32
}

// ===----------------------------------------------------------------------===//
// Test 3: Add two fractional values
// ===----------------------------------------------------------------------===//
func.func @test_add_fraction() -> f32 {
%a = arith.constant 2.5 : f32
%b = arith.constant 1.25 : f32
%res = "neura.add"(%a, %b) : (f32, f32) -> f32
// CHECK: [neura-interpreter] Executing neura.add:
// CHECK-NEXT: LHS: value = 2.500000e+00, predicate = 1
// CHECK-NEXT: RHS: value = 1.250000e+00, predicate = 1
// CHECK-NEXT: Result: value = 4.000000e+00, predicate = 1
// CHECK-NEXT: [neura-interpreter] Output: 4.000000
return %res : f32
}

// ===----------------------------------------------------------------------===//
// Test 4: Add zero and a number
// ===----------------------------------------------------------------------===//
func.func @test_add_zero() -> f32 {
%a = arith.constant 0.0 : f32
%b = arith.constant 7.0 : f32
%res = "neura.add"(%a, %b) : (f32, f32) -> f32
// CHECK: [neura-interpreter] Executing neura.add:
// CHECK-NEXT: LHS: value = 0.000000e+00, predicate = 1
// CHECK-NEXT: RHS: value = 7.000000e+00, predicate = 1
// CHECK-NEXT: Result: value = 7.000000e+00, predicate = 1
// CHECK-NEXT: [neura-interpreter] Output: 7.000000
return %res : f32
}
39 changes: 39 additions & 0 deletions test/neura/interpreter/br.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// RUN: neura-interpreter %s | FileCheck %s

func.func @test_br_with_args() -> i32 {
%0 = "neura.constant"() {value = 42 : i32} : () -> i32
// CHECK: [neura-interpreter] Executing neura.constant:
"neura.br"(%0) [^bb1] {operandSegmentSizes = array<i32: 1>} : (i32) -> ()
// CHECK-NEXT: [neura-interpreter] Executing neura.br:
// CHECK-NEXT: Target block: index 1
// CHECK-NEXT: Pass argument 0 to block parameter: value = 4.200000e+01
// CHECK-NEXT: Successfully jumped to block (index 1)
// CHECK-NEXT: Resetting operation index to start of block

^bb1(%a: i32):
// CHECK-NEXT: [neura-interpreter] Output: 42.000000
return %a : i32
}

func.func @test_br_with_multi_args() {
%0 = "neura.constant"() {value = 42 : i32} : () -> i32
// CHECK: [neura-interpreter] Executing neura.constant:
%1 = "neura.constant"() {value = 1.0 : f32} : () -> f32
// CHECK-NEXT: [neura-interpreter] Executing neura.constant:
"neura.br"(%0, %1) [^bb1] {operandSegmentSizes = array<i32: 2>} : (i32, f32) -> ()
// CHECK-NEXT: [neura-interpreter] Executing neura.br:
// CHECK-NEXT: Target block: index 1
// CHECK-NEXT: Pass argument 0 to block parameter: value = 4.200000e+01
// CHECK-NEXT: Pass argument 1 to block parameter: value = 1.000000e+00
// CHECK-NEXT: Successfully jumped to block (index 1)
// CHECK-NEXT: Resetting operation index to start of block

^bb1(%a: i32, %b: f32):
"neura.add"(%a, %a) : (i32, i32) -> i32
// CHECK-NEXT: [neura-interpreter] Executing neura.add:
// CHECK-NEXT: LHS: value = 4.200000e+01, predicate = 1
// CHECK-NEXT: RHS: value = 4.200000e+01, predicate = 1
// CHECK-NEXT: Result: value = 8.400000e+01, predicate = 1
// CHECK-NEXT: [neura-interpreter] Output: (void)
return
}
96 changes: 96 additions & 0 deletions test/neura/interpreter/cast.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// RUN: neura-interpreter %s | FileCheck %s

// int -> float
func.func @test_cast_i2f() -> f32 {
%a = arith.constant 42 : i32
%res = "neura.cast"(%a) { cast_type = "i2f" } : (i32) -> f32
// CHECK: [neura-interpreter] Executing neura.cast:
// CHECK: Input: value = 4.200000e+01, predicate = 1
// CHECK: Cast type: i2f
// CHECK: Converting integer to float: 42 -> 4.200000e+01
// CHECK: Final result: value = 4.200000e+01, predicate = true
// CHECK: [neura-interpreter] Output: 42.000000
return %res : f32
}

// float -> int
func.func @test_cast_f2i() -> i32 {
%a = arith.constant 3.14 : f32
%res = "neura.cast"(%a) { cast_type = "f2i" } : (f32) -> i32
// CHECK: [neura-interpreter] Executing neura.cast:
// CHECK: Input: value = 3.140000e+00, predicate = 1
// CHECK: Cast type: f2i
// CHECK: Converting float to integer: 3.140000e+00 -> 3
// CHECK: Final result: value = 3.000000e+00, predicate = true
// CHECK: [neura-interpreter] Output: 3.000000
return %res : i32
}

// bool -> int
func.func @test_cast_bool2i() -> i32 {
%b = arith.constant 1 : i1
%res = "neura.cast"(%b) { cast_type = "bool2i" } : (i1) -> i32
// CHECK: [neura-interpreter] Executing neura.cast:
// CHECK: Input: value = 1.000000e+00, predicate = 1
// CHECK: Cast type: bool2i
// CHECK: Converting boolean to number: true -> 1.000000e+00
// CHECK: Final result: value = 1.000000e+00, predicate = true
// CHECK: [neura-interpreter] Output: 1.000000
return %res : i32
}

// bool -> float
func.func @test_cast_bool2f() -> f32 {
%b = arith.constant 0 : i1
%res = "neura.cast"(%b) { cast_type = "bool2f" } : (i1) -> f32
// CHECK: [neura-interpreter] Executing neura.cast:
// CHECK: Input: value = 0.000000e+00, predicate = 1
// CHECK: Cast type: bool2f
// CHECK: Converting boolean to number: false -> 0.000000e+00
// CHECK: Final result: value = 0.000000e+00, predicate = true
// CHECK: [neura-interpreter] Output: 0.000000
return %res : f32
}

// int -> bool
func.func @test_cast_i2bool() -> i1 {
%a = arith.constant 100 : i32
%res = "neura.cast"(%a) { cast_type = "i2bool" } : (i32) -> i1
// CHECK: [neura-interpreter] Executing neura.cast:
// CHECK: Input: value = 1.000000e+02, predicate = 1
// CHECK: Cast type: i2bool
// CHECK: Converting number to boolean: 1.000000e+02 -> true (stored as 1.000000e+00)
// CHECK: Final result: value = 1.000000e+00, predicate = true
// CHECK: [neura-interpreter] Output: 1.000000
return %res : i1
}

// f2i with true predicate
func.func @test_cast_predicated() -> i32 {
%val = arith.constant 5.5 : f32
%pred = arith.constant 1 : i1
%res = "neura.cast"(%val, %pred) { cast_type = "f2i" } : (f32, i1) -> i32
// CHECK: [neura-interpreter] Executing neura.cast:
// CHECK: Input: value = 5.500000e+00, predicate = 1
// CHECK: Cast type: f2i
// CHECK: Predicate operand: value = 1.000000e+00, predicate = 1
// CHECK: Converting float to integer: 5.500000e+00 -> 6
// CHECK: Final result: value = 6.000000e+00, predicate = true
// CHECK: [neura-interpreter] Output: 6.000000
return %res : i32
}

// f2i with false predicate
func.func @test_cast_predicate_false() -> i32 {
%val = arith.constant 5.5 : f32
%pred = arith.constant 0 : i1
%res = "neura.cast"(%val, %pred) { cast_type = "f2i" } : (f32, i1) -> i32
// CHECK: [neura-interpreter] Executing neura.cast:
// CHECK: Input: value = 5.500000e+00, predicate = 1
// CHECK: Cast type: f2i
// CHECK: Predicate operand: value = 0.000000e+00, predicate = 1
// CHECK: Predicate is false, result is 0
// CHECK: Final result: value = 0.000000e+00, predicate = false
// CHECK: [neura-interpreter] Output: 0.000000
return %res : i32
}
72 changes: 72 additions & 0 deletions test/neura/interpreter/cond_br.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// RUN: neura-interpreter %s | FileCheck %s

func.func @test_cond_br_true() {
%cond = arith.constant 1 : i1
"neura.cond_br"(%cond) [^bb1, ^bb2] {operandSegmentSizes = array<i32: 1, 0, 0, 0>} : (i1) -> ()
// CHECK: [neura-interpreter] Executing neura.cond_br:
// CHECK-NEXT: Condition value: 1.000000e+00, condition validity: 1
// CHECK-NEXT: Condition result: true -> targeting block (index 1)
// CHECK-NEXT: Successfully jumped to true block (index 1)
// CHECK-NEXT: [neura-interpreter] Output: (void)
^bb1:
return
^bb2:
return
}

func.func @test_cond_br_false() {
%cond = arith.constant 0 : i1
"neura.cond_br"(%cond) [^bb1, ^bb2] {operandSegmentSizes = array<i32: 1, 0, 0, 0>} : (i1) -> ()
// CHECK: [neura-interpreter] Executing neura.cond_br:
// CHECK-NEXT: Condition value: 0.000000e+00, condition validity: 1
// CHECK-NEXT: Condition result: false -> targeting block (index 2)
// CHECK-NEXT: Successfully jumped to false block (index 2)
// CHECK-NEXT: [neura-interpreter] Output: (void)
^bb1:
return
^bb2:
return
}

func.func @test_cond_br_with_valid_predicate() {
%cond = arith.constant 1 : i1
%pred = arith.constant 1 : i32
"neura.cond_br"(%cond, %pred) [^bb1, ^bb2] {operandSegmentSizes = array<i32: 1, 1, 0, 0>} : (i1, i32) -> ()
// CHECK: [neura-interpreter] Executing neura.cond_br:
// CHECK-NEXT: Condition value: 1.000000e+00, condition validity: 1
// CHECK-NEXT: Predicate operand: value = 1.000000e+00, validity = 1
// CHECK-NEXT: Condition result: true -> targeting block (index 1)
// CHECK-NEXT: Successfully jumped to true block (index 1)
// CHECK-NEXT: [neura-interpreter] Output: (void)
^bb1:
return
^bb2:
return
}

func.func @test_nested_cond_br() {
%cond1 = arith.constant 1 : i1
"neura.cond_br"(%cond1) [^bb1, ^bb2] {operandSegmentSizes = array<i32: 1, 0, 0, 0>} : (i1) -> ()
// CHECK: [neura-interpreter] Executing neura.cond_br:
// CHECK-NEXT: Condition value: 1.000000e+00, condition validity: 1
// CHECK-NEXT: Condition result: true -> targeting block (index 1)
// CHECK-NEXT: Successfully jumped to true block (index 1)

^bb1:
%cond2 = arith.constant 0 : i1
"neura.cond_br"(%cond2) [^bb3, ^bb4] {operandSegmentSizes = array<i32: 1, 0, 0, 0>} : (i1) -> ()
// CHECK: [neura-interpreter] Executing neura.cond_br:
// CHECK-NEXT: Condition value: 0.000000e+00, condition validity: 1
// CHECK-NEXT: Condition result: false -> targeting block (index 4)
// CHECK-NEXT: Successfully jumped to false block (index 4)
// CHECK-NEXT: [neura-interpreter] Output: (void)

^bb2:
return

^bb3:
return

^bb4:
return
}
75 changes: 75 additions & 0 deletions test/neura/interpreter/ctrl_mov.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// RUN: neura-interpreter %s | FileCheck %s

func.func @test_ctrl_mov_basic() {
%a = "neura.reserve"() : () -> (i32)
%const = arith.constant 42 : i32

"neura.ctrl_mov"(%const, %a) : (i32, i32) -> ()

// CHECK: [neura-interpreter] Executing neura.ctrl_mov:
// CHECK-NEXT: Source: %c42_i32 = arith.constant 42 : i32
// CHECK-NEXT: Value: 4.200000e+01
// CHECK-NEXT: Predicate: true
// CHECK-NEXT: Target: %0 = neura.reserve : i32
// CHECK-NEXT: Old value: 0.000000e+00
// CHECK-NEXT: Old predicate: false
// CHECK-NEXT: Updated target placeholder:
// CHECK-NEXT: New value: 4.200000e+01
// CHECK-NEXT: New predicate: true
// CHECK-NEXT: [neura-interpreter] Output: (void)

return
}

func.func @test_ctrl_mov_chained() {
%a = "neura.reserve"() : () -> (i32)
%b = "neura.reserve"() : () -> (i32)
%const = arith.constant 10 : i32

"neura.ctrl_mov"(%const, %a) : (i32, i32) -> ()
// CHECK: [neura-interpreter] Executing neura.ctrl_mov:
// CHECK-NEXT: Source: %c10_i32 = arith.constant 10 : i32
// CHECK-NEXT: Value: 1.000000e+01
// CHECK-NEXT: Predicate: true
// CHECK-NEXT: Target: %0 = neura.reserve : i32
// CHECK-NEXT: Old value: 0.000000e+00
// CHECK-NEXT: Old predicate: false
// CHECK-NEXT: Updated target placeholder:
// CHECK-NEXT: New value: 1.000000e+01
// CHECK-NEXT: New predicate: true

"neura.ctrl_mov"(%a, %b) : (i32, i32) -> ()
// CHECK: [neura-interpreter] Executing neura.ctrl_mov:
// CHECK-NEXT: Source: %0 = neura.reserve : i32
// CHECK-NEXT: Value: 1.000000e+01
// CHECK-NEXT: Predicate: true
// CHECK-NEXT: Target: %1 = neura.reserve : i32
// CHECK-NEXT: Old value: 0.000000e+00
// CHECK-NEXT: Old predicate: false
// CHECK-NEXT: Updated target placeholder:
// CHECK-NEXT: New value: 1.000000e+01
// CHECK-NEXT: New predicate: true
// CHECK-NEXT: [neura-interpreter] Output: (void)

return
}

func.func @test_ctrl_mov_vector() {
%vec_reserve = "neura.reserve"() : () -> (vector<4xf32>)
%vec_const = "neura.constant"() {value = dense<[1.0, 2.0, 3.0, 4.0]> : vector<4xf32>} : () -> vector<4xf32>

"neura.ctrl_mov"(%vec_const, %vec_reserve) : (vector<4xf32>, vector<4xf32>) -> ()
// CHECK: [neura-interpreter] Executing neura.ctrl_mov:
// CHECK-NEXT: Source: %1 = "neura.constant"() <{value = dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00]> : vector<4xf32>}> : () -> vector<4xf32>
// CHECK-NEXT: Value: {{.*}}
// CHECK-NEXT: Predicate: true
// CHECK-NEXT: Target: %0 = neura.reserve : vector<4xf32>
// CHECK-NEXT: Old value: 0.000000e+00
// CHECK-NEXT: Old predicate: false
// CHECK-NEXT: Updated target placeholder:
// CHECK-NEXT: New value: {{.*}}
// CHECK-NEXT: New predicate: true
// CHECK-NEXT: [neura-interpreter] Output: (void)

return
}
Loading