Internal change PiperOrigin-RevId: 549214897
diff --git a/sim/kelvin_instructions.cc b/sim/kelvin_instructions.cc index 357eb9b..dbc25d6 100644 --- a/sim/kelvin_instructions.cc +++ b/sim/kelvin_instructions.cc
@@ -60,6 +60,8 @@ break; } case 1: { // Scalar log op to load an integer argument. + // The value is stored as an unsigned integer. The actual format will be + // determined with the format specifier "d" or "u". auto data = mpact::sim::generic::GetInstructionSource<uint32_t>(inst, 0, 0); state->SetLogArgs(data);
diff --git a/sim/kelvin_state.cc b/sim/kelvin_state.cc index 5fd15ca..3903548 100644 --- a/sim/kelvin_state.cc +++ b/sim/kelvin_state.cc
@@ -3,6 +3,7 @@ #include <cstdint> #include <iostream> +#include <ostream> #include <string> #include "absl/log/check.h" @@ -47,10 +48,25 @@ CHECK_GT(log_args_.size(), 0) << "Invalid program with insufficient log argurments"; if (log_args_[0].type() == typeid(uint32_t)) { - std::cout << std::any_cast<uint32_t>(log_args_[0]); + switch (print_ptr[1]) { + case 'u': + std::cout << std::any_cast<uint32_t>(log_args_[0]); + break; + case 'd': + std::cout << static_cast<int32_t>( + std::any_cast<uint32_t>(log_args_[0])); + break; + default: + std::cerr << "incorrect format" << std::endl; + break; + } } if (log_args_[0].type() == typeid(std::string)) { - std::cout << std::any_cast<std::string>(log_args_[0]); + if (print_ptr[1] == 's') { + std::cout << std::any_cast<std::string>(log_args_[0]); + } else { + std::cerr << "incorrect format" << std::endl; + } } log_args_.erase(log_args_.begin()); print_ptr += 2; // skip the format specifier too.
diff --git a/sim/test/kelvin_log_instructions_test.cc b/sim/test/kelvin_log_instructions_test.cc index 093b610..e868a62 100644 --- a/sim/test/kelvin_log_instructions_test.cc +++ b/sim/test/kelvin_log_instructions_test.cc
@@ -46,9 +46,9 @@ EXPECT_EQ(kHelloString, stdout_str); } -TEST_F(KelvinLogInstructionsTest, PrintNumer) { - constexpr char kFormatString[] = "Hello %d\n"; - constexpr uint32_t kPrintNum = 1337; +TEST_F(KelvinLogInstructionsTest, PrintUnsignedNumber) { + constexpr char kFormatString[] = "Hello %u\n"; + constexpr uint32_t kPrintNum = 2200000000; // a number > INT32_MAX // Initialize memory. auto *db = state_->db_factory()->Allocate<char>(sizeof(kFormatString)); @@ -80,7 +80,44 @@ instructions[i]->Execute(nullptr); } const std::string stdout_str = testing::internal::GetCapturedStdout(); - EXPECT_EQ("Hello 1337\n", stdout_str); + EXPECT_EQ("Hello 2200000000\n", stdout_str); +} + +TEST_F(KelvinLogInstructionsTest, PrintSignedNumber) { + constexpr char kFormatString[] = "Hello %d\n"; + constexpr int32_t kPrintNum = -1337; + + // Initialize memory. + auto *db = state_->db_factory()->Allocate<char>(sizeof(kFormatString)); + for (int i = 0; i < sizeof(kFormatString); ++i) { + db->Set<char>(i, kFormatString[i]); + } + db->DecRef(); + + std::array<InstructionPtr, 2> instructions = {CreateInstruction(), + CreateInstruction()}; + + AppendRegisterOperands(instructions[0].get(), {kelvin::sim::test::kRs1Name}, + {}); + instructions[0]->set_semantic_function( + absl::bind_front(&KelvinLogInstruction, /*mode=*/1)); // scalar log + + // Set the second instruction for the actual print out. + state_->StoreMemory(instructions[1].get(), kMemAddress, db); + AppendRegisterOperands(instructions[1].get(), {kelvin::sim::test::kRs2Name}, + {}); + instructions[1]->set_semantic_function( + absl::bind_front(&KelvinLogInstruction, /*mode=*/0)); + + SetRegisterValues<int32_t>({{kelvin::sim::test::kRs1Name, kPrintNum}}); + SetRegisterValues<uint32_t>({{kelvin::sim::test::kRs2Name, kMemAddress}}); + + testing::internal::CaptureStdout(); + for (int i = 0; i < instructions.size(); ++i) { + instructions[i]->Execute(nullptr); + } + const std::string stdout_str = testing::internal::GetCapturedStdout(); + EXPECT_EQ("Hello -1337\n", stdout_str); } TEST_F(KelvinLogInstructionsTest, PrintCharacterStream) {