Skip to content
This repository has been archived by the owner on Jul 8, 2022. It is now read-only.

Commit

Permalink
[DSLX] trace_fmt! support for signed values (e.g. s32) printed signed…
Browse files Browse the repository at this point in the history
…-ly.

Important aid in DSL level debugging.

PiperOrigin-RevId: 455507157
  • Loading branch information
cdleary authored and copybara-github committed Jun 17, 2022
1 parent 3ab5944 commit 7a4d1b9
Show file tree
Hide file tree
Showing 19 changed files with 159 additions and 63 deletions.
9 changes: 8 additions & 1 deletion docs_src/dslx_reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -1939,12 +1939,16 @@ dumping of current values to stdout. For example:
fn shifty(x: u8, y: u3) -> u8 {
let _ = trace_fmt!("x: {:x} y: {}", x, y);
// Note: y looks different as a negative number when the high bit is set.
let _ = trace_fmt!("y as s8: {}", y as s2);
x << y
}
#![test]
fn test_shifty() {
assert_eq(shifty(u8:0x42, u3:4), u8:0x20)
let _ = assert_eq(shifty(u8:0x42, u3:4), u8:0x20);
let _ = assert_eq(shifty(u8:0x42, u3:7), u8:0);
()
}
```

Expand All @@ -1955,6 +1959,9 @@ corresponding source position:
[...]
[ RUN UNITTEST ] test_shifty
I0510 14:31:17.516227 1247677 bytecode_interpreter.cc:994] x: 42 y: 4
I0510 14:31:17.516227 1247677 bytecode_interpreter.cc:994] y as s8: 4
I0510 14:31:17.516227 1247677 bytecode_interpreter.cc:994] x: 42 y: 7
I0510 14:31:17.516227 1247677 bytecode_interpreter.cc:994] y as s8: -1
[ OK ]
[...]
```
Expand Down
7 changes: 4 additions & 3 deletions xls/codegen/vast.cc
Original file line number Diff line number Diff line change
Expand Up @@ -707,15 +707,16 @@ std::string Literal::Emit(LineInfo* line_info) const {
LineInfoEnd(line_info, this);
if (format_ == FormatPreference::kDefault) {
XLS_CHECK_LE(bits_.bit_count(), 32);
return absl::StrFormat("%s", bits_.ToString(FormatPreference::kDecimal));
return absl::StrFormat("%s",
bits_.ToString(FormatPreference::kUnsignedDecimal));
}
if (format_ == FormatPreference::kDecimal) {
if (format_ == FormatPreference::kUnsignedDecimal) {
std::string prefix;
if (emit_bit_count_) {
prefix = absl::StrFormat("%d'd", bits_.bit_count());
}
return absl::StrFormat("%s%s", prefix,
bits_.ToString(FormatPreference::kDecimal));
bits_.ToString(FormatPreference::kUnsignedDecimal));
}
if (format_ == FormatPreference::kBinary) {
return absl::StrFormat(
Expand Down
18 changes: 9 additions & 9 deletions xls/codegen/vast_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -321,9 +321,9 @@ endmodule)");

TEST_P(VastTest, Literals) {
VerilogFile f(UseSystemVerilog());
EXPECT_EQ("32'd44",
f.Literal(UBits(44, 32), SourceInfo(), FormatPreference::kDecimal)
->Emit(nullptr));
EXPECT_EQ("32'd44", f.Literal(UBits(44, 32), SourceInfo(),
FormatPreference::kUnsignedDecimal)
->Emit(nullptr));
EXPECT_EQ("1'b1",
f.Literal(UBits(1, 1), SourceInfo(), FormatPreference::kBinary)
->Emit(nullptr));
Expand All @@ -344,9 +344,9 @@ TEST_P(VastTest, Literals) {
Bits huge,
ParseNumber("0xabcd_000_0000_1234_4321_0000_aaaa_bbbb_cccc_dddd_eeee"));

EXPECT_EQ(
f.Literal(b0, SourceInfo(), FormatPreference::kDecimal)->Emit(nullptr),
"1'd0");
EXPECT_EQ(f.Literal(b0, SourceInfo(), FormatPreference::kUnsignedDecimal)
->Emit(nullptr),
"1'd0");

EXPECT_EQ(f.Literal(b2, SourceInfo(), FormatPreference::kHex)->Emit(nullptr),
"3'h2");
Expand All @@ -365,9 +365,9 @@ TEST_P(VastTest, Literals) {
EXPECT_EQ(
f.Literal(b1234, SourceInfo(), FormatPreference::kHex)->Emit(nullptr),
"55'h00_0000_0000_04d2");
EXPECT_EQ(
f.Literal(b1234, SourceInfo(), FormatPreference::kDecimal)->Emit(nullptr),
"55'd1234");
EXPECT_EQ(f.Literal(b1234, SourceInfo(), FormatPreference::kUnsignedDecimal)
->Emit(nullptr),
"55'd1234");
EXPECT_EQ(
f.Literal(b1234, SourceInfo(), FormatPreference::kBinary)->Emit(nullptr),
"55'b000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0100_"
Expand Down
9 changes: 2 additions & 7 deletions xls/dslx/bytecode_interpreter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -969,14 +969,9 @@ absl::Status BytecodeInterpreter::EvalSwap(const Bytecode& bytecode) {
pieces.push_front(absl::get<std::string>(trace_element));
} else {
XLS_RET_CHECK(!stack.empty());
// TODO(rspringer): 2022-02-22: This JIT prints values via the IR's
// Value::ToHumanString() function. The problem is that it doesn't print
// out negative numbers, which is lossy and confusing. Find a way to unify
// these two somehow?
XLS_ASSIGN_OR_RETURN(InterpValue value, Pop(stack));
XLS_ASSIGN_OR_RETURN(Value ir_value, value.ConvertToIr());
pieces.push_front(
ir_value.ToHumanString(absl::get<FormatPreference>(trace_element)));
pieces.push_front(value.ToString(
/*humanize=*/true, absl::get<FormatPreference>(trace_element)));
}
}

Expand Down
8 changes: 5 additions & 3 deletions xls/dslx/interp_value.cc
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ static std::string BitsToString(const InterpValue& v, FormatPreference format,
switch (v.tag()) {
case InterpValueTag::kUBits: {
std::string value_str = bits.ToString(format);
if (format == FormatPreference::kSignedDecimal && bits.msb()) {
value_str = absl::StrCat("-", bits_ops::Negate(bits).ToString(format));
}
if (!include_type_prefix) {
return value_str;
}
Expand All @@ -116,7 +119,7 @@ static std::string BitsToString(const InterpValue& v, FormatPreference format,
}
case InterpValueTag::kSBits: {
std::string value_str = bits.ToString(format);
if ((format == FormatPreference::kDecimal ||
if ((format == FormatPreference::kSignedDecimal ||
format == FormatPreference::kDefault) &&
bits.msb()) {
// If we're a signed number in decimal format, give the value for the
Expand Down Expand Up @@ -155,8 +158,7 @@ std::string InterpValue::ToString(bool humanize,
case InterpValueTag::kUBits:
case InterpValueTag::kSBits:
return BitsToString(*this, format,
/*include_type_prefix=*/!humanize ||
format == FormatPreference::kBinary);
/*include_type_prefix=*/!humanize);
case InterpValueTag::kArray:
return absl::StrFormat("[%s]", make_guts());
case InterpValueTag::kTuple:
Expand Down
14 changes: 10 additions & 4 deletions xls/dslx/interp_value_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,24 @@ TEST(InterpValueTest, FormatU8) {
auto ff = InterpValue::MakeUBits(/*bit_count=*/8, /*value=*/0xff);
EXPECT_EQ(ff.ToString(), "u8:255");
EXPECT_EQ(ff.ToString(/*humanize=*/true, FormatPreference::kHex), "0xff");
EXPECT_EQ(ff.ToString(/*humanize=*/true, FormatPreference::kDecimal), "255");
EXPECT_EQ(ff.ToString(/*humanize=*/true, FormatPreference::kSignedDecimal),
"-1");
EXPECT_EQ(ff.ToString(/*humanize=*/true, FormatPreference::kUnsignedDecimal),
"255");
EXPECT_EQ(ff.ToString(/*humanize=*/true, FormatPreference::kBinary),
"u8:0b1111_1111");
"0b1111_1111");
}

TEST(InterpValueTest, FormatS8) {
auto ff = InterpValue::MakeSBits(/*bit_count=*/8, /*value=*/-1);
EXPECT_EQ(ff.ToString(), "s8:-1");
EXPECT_EQ(ff.ToString(/*humanize=*/true, FormatPreference::kHex), "0xff");
EXPECT_EQ(ff.ToString(/*humanize=*/true, FormatPreference::kDecimal), "-1");
EXPECT_EQ(ff.ToString(/*humanize=*/true, FormatPreference::kUnsignedDecimal),
"255");
EXPECT_EQ(ff.ToString(/*humanize=*/true, FormatPreference::kSignedDecimal),
"-1");
EXPECT_EQ(ff.ToString(/*humanize=*/true, FormatPreference::kBinary),
"s8:0b1111_1111");
"0b1111_1111");
}

TEST(InterpValueTest, BitsEquivalence) {
Expand Down
34 changes: 28 additions & 6 deletions xls/dslx/interpreter/interpreter_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,8 +205,8 @@ def test_tuple_index(self):

def test_for_over_array(self):
program = textwrap.dedent("""\
#![test]
fn for_over_array_test() {
#![test]
fn for_over_array_test() {
let a: u32[3] = u32[3]:[1, 2, 3];
let result: u32 = for (value, accum): (u32, u32) in a {
accum + value
Expand Down Expand Up @@ -417,23 +417,45 @@ def test_trace(self):
self.assertIn('4:21-4:32: 1', result.stderr)
self.assertIn('6:21-6:32: 2', result.stderr)

def test_trace_s32(self):
program = """
#![test]
fn trace_test() {
let x = u32:4;
let _ = trace!(x);
let x = s32:-1;
let _ = trace!(x);
()
}
"""
program_file = self.create_tempfile(content=program)
# Trace is logged with XLS_LOG(INFO) so log to stderr to capture output.
cmd = [
_INTERP_PATH, '--compare=none', '--alsologtostderr',
program_file.full_path
]
result = subp.run(cmd, stderr=subp.PIPE, encoding='utf-8', check=True)
self.assertIn('5:21-5:24: 4', result.stderr)
self.assertIn('7:21-7:24: -1', result.stderr)

def test_trace_fmt_hello(self):
program = """
fn main() {
let x = u8:0xF0;
let _ = trace_fmt!("Hello world!");
let _ = trace_fmt!("x is {}, {:#x} in hex and {:#b} in binary", x, x, x);
()
}
#![test]
fn hello_test() {
let x = u8:0xF0;
let _ = trace_fmt!("Hello world!\n");
let _ = trace_fmt!("x is {}, {:#x} in hex and {:#b} in binary", x, x, x);
()
main()
}
"""
program_file = self.create_tempfile(content=program)
cmd = [_INTERP_PATH, '--alsologtostderr', program_file.full_path]
result = subp.run(cmd, stderr=subp.PIPE, encoding='utf-8', check=True)
print(result.stderr)
self.assertIn('Hello world!', result.stderr)
self.assertIn('x is 240, 0xf0 in hex and 0b1111_0000 in binary',
result.stderr)
Expand Down
4 changes: 2 additions & 2 deletions xls/dslx/mangle.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ std::string MangleInterpValue(const InterpValue& value) {
if (value.IsBits() || value.IsEnum()) {
auto bits_value = InterpValue::MakeBits(/*is_signed=*/value.IsSigned(),
value.GetBitsOrDie());
std::string s =
bits_value.ToString(/*humanize=*/true, FormatPreference::kDecimal);
std::string s = bits_value.ToString(/*humanize=*/true,
FormatPreference::kUnsignedDecimal);
// Negatives are not valid characters in IR symbols so replace leading '-'
// with 'm'.
return absl::StrReplaceAll(s, {{"-", "m"}});
Expand Down
4 changes: 2 additions & 2 deletions xls/dslx/run_routines.cc
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ absl::Status RunComparator::RunComparison(
const char* mode_str = nullptr;
Value ir_result;
switch (mode_) {
case CompareMode::kJit: {
case CompareMode::kJit: { // Compare to IR JIT.
// TODO(https://github.com/google/xls/issues/506): Also compare events
// once the DSLX interpreter supports them (and the JIT supports traces).
XLS_ASSIGN_OR_RETURN(FunctionJit * jit,
Expand All @@ -148,7 +148,7 @@ absl::Status RunComparator::RunComparison(
mode_str = "JIT";
break;
}
case CompareMode::kInterpreter: {
case CompareMode::kInterpreter: { // Compare to IR interpreter.
XLS_ASSIGN_OR_RETURN(ir_result, DropInterpreterEvents(InterpretFunction(
ir_function, ir_args)));
mode_str = "interpreter";
Expand Down
18 changes: 16 additions & 2 deletions xls/ir/bits.cc
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ std::string Bits::ToString(FormatPreference preference,
bool include_bit_count) const {
if (preference == FormatPreference::kDefault) {
if (bit_count() <= 64) {
preference = FormatPreference::kDecimal;
preference = FormatPreference::kUnsignedDecimal;
} else {
preference = FormatPreference::kHex;
}
Expand All @@ -278,7 +278,21 @@ std::string Bits::ToString(FormatPreference preference,
std::string Bits::ToRawDigits(FormatPreference preference,
bool emit_leading_zeros) const {
XLS_CHECK_NE(preference, FormatPreference::kDefault);
if (preference == FormatPreference::kDecimal) {
if (preference == FormatPreference::kSignedDecimal) {
// Leading zeros don't make a lot of sense in decimal format as there is no
// clean correspondence between decimal digits and binary digits.
XLS_CHECK(!emit_leading_zeros)
<< "emit_leading_zeros not supported for decimal format.";

// TODO(google/xls#461): 2019-04-03 Add support for arbitrary width decimal
// emission.
XLS_CHECK(FitsInInt64())
<< "Decimal output not supported for values which do "
"not fit in an int64_t";
return absl::StrCat(ToInt64().value());
}

if (preference == FormatPreference::kUnsignedDecimal) {
// Leading zeros don't make a lot of sense in decimal format as there is no
// clean correspondence between decimal digits and binary digits.
XLS_CHECK(!emit_leading_zeros)
Expand Down
21 changes: 15 additions & 6 deletions xls/ir/bits_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -317,28 +317,36 @@ TEST(BitsTest, ToString) {
};

Bits empty_bits(0);
EXPECT_EQ(empty_bits.ToString(FormatPreference::kDecimal), "0");
EXPECT_EQ(empty_bits.ToString(FormatPreference::kUnsignedDecimal), "0");
EXPECT_EQ(empty_bits.ToString(FormatPreference::kSignedDecimal), "0");
test_hex(empty_bits, "0x0");
test_binary(empty_bits, "0b0");
EXPECT_EQ(empty_bits.ToString(FormatPreference::kDecimal,
EXPECT_EQ(empty_bits.ToString(FormatPreference::kUnsignedDecimal,
/*include_bit_count=*/true),
"0 [0 bits]");
EXPECT_EQ(empty_bits.ToString(FormatPreference::kSignedDecimal,
/*include_bit_count=*/true),
"0 [0 bits]");

Bits b1 = UBits(1, 1);
EXPECT_EQ(b1.ToString(FormatPreference::kDecimal), "1");
EXPECT_EQ(b1.ToString(FormatPreference::kUnsignedDecimal), "1");
EXPECT_EQ(b1.ToString(FormatPreference::kSignedDecimal), "-1");
test_hex(b1, "0x1");
test_binary(b1, "0b1");

test_binary(UBits(1, 16), "0b1");
test_hex(UBits(1, 16), "0x1");

Bits b42 = UBits(42, 7);
EXPECT_EQ(b42.ToString(FormatPreference::kDecimal), "42");
EXPECT_EQ(b42.ToString(FormatPreference::kUnsignedDecimal), "42");
EXPECT_EQ(b42.ToString(FormatPreference::kSignedDecimal), "42");
test_hex(b42, "0x2a");
test_binary(b42, "0b10_1010");

Bits prime64 = PrimeBits(64);
EXPECT_EQ(prime64.ToString(FormatPreference::kDecimal),
EXPECT_EQ(prime64.ToString(FormatPreference::kUnsignedDecimal),
"2892025783495830204");
EXPECT_EQ(prime64.ToString(FormatPreference::kSignedDecimal),
"2892025783495830204");
test_hex(prime64, "0x2822_8a20_a28a_2abc");
test_binary(
Expand All @@ -363,7 +371,8 @@ TEST(BitsTest, ToString) {

TEST(BitsTest, ToRawString) {
Bits empty_bits(0);
EXPECT_EQ(empty_bits.ToRawDigits(FormatPreference::kDecimal), "0");
EXPECT_EQ(empty_bits.ToRawDigits(FormatPreference::kUnsignedDecimal), "0");
EXPECT_EQ(empty_bits.ToRawDigits(FormatPreference::kSignedDecimal), "0");
EXPECT_EQ(empty_bits.ToRawDigits(FormatPreference::kHex), "0");
EXPECT_EQ(empty_bits.ToRawDigits(FormatPreference::kBinary), "0");
EXPECT_EQ(empty_bits.ToRawDigits(FormatPreference::kHex,
Expand Down
20 changes: 14 additions & 6 deletions xls/ir/format_preference.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ absl::string_view FormatPreferenceToString(FormatPreference preference) {
return "default";
case FormatPreference::kBinary:
return "binary";
case FormatPreference::kDecimal:
return "decimal";
case FormatPreference::kSignedDecimal:
return "signed-decimal";
case FormatPreference::kUnsignedDecimal:
return "unsigned-decimal";
case FormatPreference::kHex:
return "hex";
case FormatPreference::kPlainBinary:
Expand All @@ -43,7 +45,9 @@ absl::string_view FormatPreferenceToXlsSpecifier(FormatPreference preference) {
return "{}";
case FormatPreference::kBinary:
return "{:#b}";
case FormatPreference::kDecimal:
case FormatPreference::kUnsignedDecimal:
return "{:u}";
case FormatPreference::kSignedDecimal:
return "{:d}";
case FormatPreference::kHex:
return "{:#x}";
Expand All @@ -66,8 +70,10 @@ absl::string_view FormatPreferenceToVerilogSpecifier(
// - decide that the default format (or at least the format associated
// with {}) is decimal after all (matches Rust)
return "%d";
case FormatPreference::kDecimal:
case FormatPreference::kSignedDecimal:
return "%d";
case FormatPreference::kUnsignedDecimal:
return "%u";
// Technically, the binary and hex format specifications are slightly wrong
// because Verilog simulators don't break up long values with underscores as
// XLS does. Practically speaking, though, it isn't worth doing a complex,
Expand All @@ -93,8 +99,10 @@ absl::StatusOr<FormatPreference> FormatPreferenceFromString(
return FormatPreference::kBinary;
} else if (s == "hex") {
return FormatPreference::kHex;
} else if (s == "decimal") {
return FormatPreference::kDecimal;
} else if (s == "signed-decimal") {
return FormatPreference::kSignedDecimal;
} else if (s == "unsigned-decimal") {
return FormatPreference::kUnsignedDecimal;
} else if (s == "plain_binary") {
return FormatPreference::kPlainBinary;
} else if (s == "plain_hex") {
Expand Down
3 changes: 2 additions & 1 deletion xls/ir/format_preference.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ enum class FormatPreference {
// hexadecimal is used.
kDefault,
kBinary,
kDecimal,
kSignedDecimal,
kUnsignedDecimal,
kHex,
kPlainBinary, // No 0b prefix and no separators as in Rust {:b} and Verilog
// %b
Expand Down
Loading

0 comments on commit 7a4d1b9

Please sign in to comment.