Skip to content

Commit d7ec099

Browse files
authored
[Arcilator] Print full values rather than truncating them. (#9120)
1 parent 90757b5 commit d7ec099

File tree

9 files changed

+142
-66
lines changed

9 files changed

+142
-66
lines changed

integration_test/arcilator/JIT/basic.mlir

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// RUN: arcilator %s --run --jit-entry=main | FileCheck %s
22
// REQUIRES: arcilator-jit
33

4-
// CHECK: output = 5
4+
// CHECK: output = 05
55

66
hw.module @adder(in %a: i8, in %b: i8, out c: i8) {
77
%res = comb.add %a, %b : i8

integration_test/arcilator/JIT/counter.mlir

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,16 @@
22
// REQUIRES: arcilator-jit
33

44
// CHECK: counter_value = 0
5-
// CHECK-NEXT: counter_value = 1
6-
// CHECK-NEXT: counter_value = 2
7-
// CHECK-NEXT: counter_value = 3
8-
// CHECK-NEXT: counter_value = 4
9-
// CHECK-NEXT: counter_value = 5
10-
// CHECK-NEXT: counter_value = 6
11-
// CHECK-NEXT: counter_value = 7
12-
// CHECK-NEXT: counter_value = 8
13-
// CHECK-NEXT: counter_value = 9
14-
// CHECK-NEXT: counter_value = a
5+
// CHECK-NEXT: counter_value = 01
6+
// CHECK-NEXT: counter_value = 02
7+
// CHECK-NEXT: counter_value = 03
8+
// CHECK-NEXT: counter_value = 04
9+
// CHECK-NEXT: counter_value = 05
10+
// CHECK-NEXT: counter_value = 06
11+
// CHECK-NEXT: counter_value = 07
12+
// CHECK-NEXT: counter_value = 08
13+
// CHECK-NEXT: counter_value = 09
14+
// CHECK-NEXT: counter_value = 0a
1515

1616
hw.module @counter(in %clk: i1, out o: i8) {
1717
%seq_clk = seq.to_clock %clk

integration_test/arcilator/JIT/div-by-zero.mlir

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
// RUN: arcilator %s --run --jit-entry=main | FileCheck %s
22
// REQUIRES: arcilator-jit
3-
// CHECK: divu = 0{{$}}
4-
// CHECK: divs = 0{{$}}
5-
// CHECK: modu = 0{{$}}
6-
// CHECK: mods = 0{{$}}
3+
// CHECK: divu = 00{{$}}
4+
// CHECK: divs = 00{{$}}
5+
// CHECK: modu = 00{{$}}
6+
// CHECK: mods = 00{{$}}
77

88
hw.module @Baz(in %a: i8, in %b: i8, out divu: i8, out divs: i8, out modu: i8, out mods: i8) {
99
%zero = hw.constant 0 : i8

integration_test/arcilator/JIT/dpi.mlir

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@
88
void mul_shared(int a, int b, int *result) { *result = a * b; }
99

1010
//--- dpi.mlir
11-
// CHECK: c = 0
12-
// CHECK-NEXT: d = 0
13-
// CHECK-NEXT: c = 5
14-
// CHECK-NEXT: d = 6
11+
// CHECK: c = {{0*}}0
12+
// CHECK-NEXT: d = {{0*}}0
13+
// CHECK-NEXT: c = {{0*}}5
14+
// CHECK-NEXT: d = {{0*}}6
1515
sim.func.dpi @mul_shared(in %a : i32, in %b : i32, out c : i32)
1616
sim.func.dpi @add_mlir(in %a : i32, in %b : i32, out c : i32) attributes {verilogName = "add_mlir_impl"}
1717
func.func @add_mlir_impl(%arg0: i32, %arg1: i32, %arg2: !llvm.ptr) {

integration_test/arcilator/JIT/print.mlir

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// RUN: arcilator %s --run | FileCheck %s
22
// REQUIRES: arcilator-jit
33

4-
// CHECK: result = 4
4+
// CHECK: result = {{0*}}4
55

66
func.func @entry() {
77
%four = arith.constant 4 : i32

integration_test/arcilator/JIT/reg.mlir

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
// RUN: arcilator %s --run --jit-entry=main | FileCheck %s
22
// REQUIRES: arcilator-jit
33

4-
// CHECK: o1 = 2
5-
// CHECK-NEXT: o2 = 5
6-
// CHECK-NEXT: o1 = 3
7-
// CHECK-NEXT: o2 = 6
8-
// CHECK-NEXT: o1 = 4
9-
// CHECK-NEXT: o2 = 7
4+
// CHECK: o1 = 02
5+
// CHECK-NEXT: o2 = 05
6+
// CHECK-NEXT: o1 = 03
7+
// CHECK-NEXT: o2 = 06
8+
// CHECK-NEXT: o1 = 04
9+
// CHECK-NEXT: o2 = 07
1010

1111
func.func private @random() -> i32 {
1212
%0 = arith.constant 2 : i32

lib/Conversion/ArcToLLVM/LowerArcToLLVM.cpp

Lines changed: 58 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "mlir/Pass/Pass.h"
3535
#include "mlir/Transforms/DialectConversion.h"
3636
#include "llvm/Support/Debug.h"
37+
#include "llvm/Support/FormatVariadic.h"
3738

3839
#define DEBUG_TYPE "lower-arc-to-llvm"
3940

@@ -534,25 +535,53 @@ struct SimEmitValueOpLowering
534535
if (!moduleOp)
535536
return failure();
536537

537-
// Cast the value to a size_t.
538-
// FIXME: like the rest of MLIR, this assumes sizeof(intptr_t) ==
539-
// sizeof(size_t) on the target architecture.
540-
Value toPrint = adaptor.getValue();
541-
DataLayout layout = DataLayout::closest(op);
542-
llvm::TypeSize sizeOfSizeT =
543-
layout.getTypeSizeInBits(rewriter.getIndexType());
544-
assert(!sizeOfSizeT.isScalable() &&
545-
sizeOfSizeT.getFixedValue() <= std::numeric_limits<unsigned>::max());
546-
bool truncated = false;
547-
if (valueType.getWidth() > sizeOfSizeT) {
548-
toPrint = LLVM::TruncOp::create(
549-
rewriter, loc,
550-
IntegerType::get(getContext(), sizeOfSizeT.getFixedValue()), toPrint);
551-
truncated = true;
552-
} else if (valueType.getWidth() < sizeOfSizeT)
553-
toPrint = LLVM::ZExtOp::create(
554-
rewriter, loc,
555-
IntegerType::get(getContext(), sizeOfSizeT.getFixedValue()), toPrint);
538+
SmallVector<Value> printfVariadicArgs;
539+
SmallString<16> printfFormatStr;
540+
int remainingBits = valueType.getWidth();
541+
Value value = adaptor.getValue();
542+
543+
// Assumes the target platform uses 64bit for long long ints (%llx
544+
// formatter).
545+
constexpr llvm::StringRef intFormatter = "llx";
546+
auto intType = IntegerType::get(getContext(), 64);
547+
Value shiftValue = LLVM::ConstantOp::create(
548+
rewriter, loc, rewriter.getIntegerAttr(valueType, intType.getWidth()));
549+
550+
if (valueType.getWidth() < intType.getWidth()) {
551+
int width = llvm::divideCeil(valueType.getWidth(), 4);
552+
printfFormatStr = llvm::formatv("%0{0}{1}", width, intFormatter);
553+
printfVariadicArgs.push_back(
554+
LLVM::ZExtOp::create(rewriter, loc, intType, value));
555+
} else {
556+
// Process the value in 64 bit chunks, starting from the least significant
557+
// bits. Since we append chunks in low-to-high order, we reverse the
558+
// vector to print them in the correct high-to-low order.
559+
int otherChunkWidth = intType.getWidth() / 4;
560+
int firstChunkWidth =
561+
llvm::divideCeil(valueType.getWidth() % intType.getWidth(), 4);
562+
if (firstChunkWidth == 0) { // print the full 64-bit hex or a subset.
563+
firstChunkWidth = otherChunkWidth;
564+
}
565+
566+
std::string firstChunkFormat =
567+
llvm::formatv("%0{0}{1}", firstChunkWidth, intFormatter);
568+
std::string otherChunkFormat =
569+
llvm::formatv("%0{0}{1}", otherChunkWidth, intFormatter);
570+
571+
for (int i = 0; remainingBits > 0; ++i) {
572+
// Append 64-bit chunks to the printf arguments, in low-to-high
573+
// order. The integer is printed in hex format with zero padding.
574+
printfVariadicArgs.push_back(
575+
LLVM::TruncOp::create(rewriter, loc, intType, value));
576+
577+
// Zero-padded format specifier for fixed width, e.g. %01llx for 4 bits.
578+
printfFormatStr.append(i == 0 ? firstChunkFormat : otherChunkFormat);
579+
580+
value =
581+
LLVM::LShrOp::create(rewriter, loc, value, shiftValue).getResult();
582+
remainingBits -= intType.getWidth();
583+
}
584+
}
556585

557586
// Lookup of create printf function symbol.
558587
auto printfFunc = LLVM::lookupOrCreateFn(
@@ -563,7 +592,6 @@ struct SimEmitValueOpLowering
563592

564593
// Insert the format string if not already available.
565594
SmallString<16> formatStrName{"_arc_sim_emit_"};
566-
formatStrName.append(truncated ? "trunc_" : "full_");
567595
formatStrName.append(adaptor.getValueName());
568596
LLVM::GlobalOp formatStrGlobal;
569597
if (!(formatStrGlobal =
@@ -572,9 +600,8 @@ struct SimEmitValueOpLowering
572600

573601
SmallString<16> formatStr = adaptor.getValueName();
574602
formatStr.append(" = ");
575-
if (truncated)
576-
formatStr.append("(truncated) ");
577-
formatStr.append("%zx\n");
603+
formatStr.append(printfFormatStr);
604+
formatStr.append("\n");
578605
SmallVector<char> formatStrVec{formatStr.begin(), formatStr.end()};
579606
formatStrVec.push_back(0);
580607

@@ -590,8 +617,14 @@ struct SimEmitValueOpLowering
590617

591618
Value formatStrGlobalPtr =
592619
LLVM::AddressOfOp::create(rewriter, loc, formatStrGlobal);
593-
rewriter.replaceOpWithNewOp<LLVM::CallOp>(
594-
op, printfFunc.value(), ValueRange{formatStrGlobalPtr, toPrint});
620+
621+
// Add the format string to the end, and reverse the vector to print them in
622+
// the correct high-to-low order with the format string at the beginning.
623+
printfVariadicArgs.push_back(formatStrGlobalPtr);
624+
std::reverse(printfVariadicArgs.begin(), printfVariadicArgs.end());
625+
626+
rewriter.replaceOpWithNewOp<LLVM::CallOp>(op, printfFunc.value(),
627+
printfVariadicArgs);
595628

596629
return success();
597630
}

test/Dialect/Arc/lower-sim.mlir

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
// RUN: arcilator %s --emit-mlir | FileCheck %s
22

3-
module attributes { dlti.dl_spec = #dlti.dl_spec<
4-
#dlti.dl_entry<index, 16>
5-
> } {
3+
module {
64
hw.module @id(in %i: i8, in %j: i8, out o: i8) {
75
hw.output %i : i8
86
}
97

10-
// CHECK-DAG: llvm.mlir.global internal constant @[[format_str:.*]]("result = %zx\0A\00")
11-
// CHECK-DAG: llvm.mlir.global internal constant @[[format_str2:.*]]("result2 = %zx\0A\00")
12-
// CHECK-DAG: llvm.mlir.global internal constant @[[format_str_trunc:.*]]("result = (truncated) %zx\0A\00")
138

9+
// CHECK-DAG: llvm.mlir.global internal constant @[[format_str2:.*]]("result2 = %02llx\0A\00")
10+
// CHECK-DAG: llvm.mlir.global internal constant @[[format_str:.*]]("result = %02llx\0A\00")
11+
// CHECK-DAG: llvm.mlir.global internal constant @[[format_str3:.*]]("result3 = %012llx%016llx\0A\00")
1412
// CHECK-LABEL: llvm.func @full
1513
func.func @full() {
1614
%c = arith.constant 24 : i8
@@ -37,7 +35,7 @@ module attributes { dlti.dl_spec = #dlti.dl_spec<
3735
// CHECK-NEXT: %[[result:.*]] = llvm.load %[[o_ptr]] : !llvm.ptr -> i8
3836
%result = arc.sim.get_port %model, "o" : i8, !arc.sim.instance<@id>
3937

40-
// CHECK-DAG: %[[to_print:.*]] = llvm.zext %[[result]] : i8 to i16
38+
// CHECK-DAG: %[[to_print:.*]] = llvm.zext %[[result]] : i8 to i64
4139
// CHECK: llvm.call @printf(%[[format_str_ptr]], %[[to_print]])
4240
arc.sim.emit "result", %result : i8
4341

@@ -52,14 +50,17 @@ module attributes { dlti.dl_spec = #dlti.dl_spec<
5250
return
5351
}
5452

55-
// CHECK-LABEL: llvm.func @trunc
56-
func.func @trunc() {
57-
%v = arith.constant 0 : i32
58-
// CHECK-DAG: %[[val_i32:.*]] = llvm.mlir.constant(0 : i32) : i32
59-
// CHECK-DAG: %[[val_truncated:.*]] = llvm.trunc %[[val_i32]] : i32 to i16
60-
// CHECK-DAG: %[[format_str_trunc_ptr:.*]] = llvm.mlir.addressof @[[format_str_trunc]] : !llvm.ptr
61-
// CHECK-DAG: llvm.call @printf(%[[format_str_trunc_ptr]], %[[val_truncated]])
62-
arc.sim.emit "result", %v : i32
53+
54+
// CHECK-LABEL: llvm.func @print_i112
55+
// CHECK-SAME: %[[arg0:.*]]: i112
56+
func.func @print_i112(%v: i112) {
57+
// CHECK: %[[format_str3_ptr:.*]] = llvm.mlir.addressof @[[format_str3]] : !llvm.ptr
58+
// CHECK: %[[shift:.*]] = llvm.mlir.constant(64 : i112)
59+
// CHECK: %[[lower:.*]] = llvm.trunc %[[arg0]]
60+
// CHECK: %[[shifted:.*]] = llvm.lshr %[[arg0]], %[[shift]]
61+
// CHECK: %[[higher:.*]] = llvm.trunc %[[shifted]]
62+
// CHECK: llvm.call @printf(%[[format_str3_ptr]], %[[higher]], %[[lower]])
63+
arc.sim.emit "result3", %v : i112
6364
return
6465
}
6566
}

test/arcilator/emit-values.mlir

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// RUN: arcilator --run %s | FileCheck %s
2+
module {
3+
func.func @entry() {
4+
// CHECK: a1 = 1
5+
%a1 = arith.constant 0x1 : i4
6+
arc.sim.emit "a1", %a1 : i4
7+
8+
// CHECK: v1 = 0001
9+
%v1 = arith.constant 0x1 : i16
10+
arc.sim.emit "v1", %v1 : i16
11+
12+
// CHECK: v2 = abcdef
13+
%v2 = arith.constant 0xABCDEF : i24
14+
arc.sim.emit "v2", %v2 : i24
15+
16+
// CHECK: v3 = 0123456789abcdef
17+
%v3 = arith.constant 0x0123456789ABCDEF : i64
18+
arc.sim.emit "v3", %v3 : i64
19+
20+
// CHECK: v4 = 0000000000000001
21+
%v4 = arith.constant 1 : i64
22+
arc.sim.emit "v4", %v4 : i64
23+
24+
// CHECK: v5 = 7a
25+
%v5 = arith.constant 0x7A : i7
26+
arc.sim.emit "v5", %v5 : i7
27+
28+
// CHECK: v6 = 10000000000b
29+
%v6 = arith.constant 0x10000000000B : i47
30+
arc.sim.emit "v6", %v6 : i47
31+
32+
// CHECK: v7 = 1
33+
%v7 = arith.constant 0x1 : i1
34+
arc.sim.emit "v7", %v7 : i1
35+
36+
// CHECK: v8 = 0fde6741e3a44d997e80d393ae643ee0fd9
37+
%v8 = arith.constant 0xfde6741e3a44d997e80d393ae643ee0fd9 : i137
38+
arc.sim.emit "v8", %v8 : i137
39+
40+
return
41+
}
42+
}

0 commit comments

Comments
 (0)