Skip to content

Commit

Permalink
Merge pull request #11 from Emoun/master
Browse files Browse the repository at this point in the history
Fix reading of input on MacOs
  • Loading branch information
schoeberl authored Aug 7, 2020
2 parents 43f4ae6 + 2336742 commit 4d4ec71
Show file tree
Hide file tree
Showing 11 changed files with 109 additions and 35 deletions.
11 changes: 5 additions & 6 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@ cache:
- build/

jobs:
allow_failures:
- os: osx
stage: "Test"
include:
- stage: "Clear cache"
# Bionic
Expand All @@ -30,15 +27,19 @@ jobs:
os: osx
before_script:
- brew install libelf
before_cache: touch build/osx_build_$TRAVIS_TEST_RESULT

- stage: "Test"
# Bionic
script: ci/test.sh
before_script:
- sudo apt-get update -qq
- sudo apt-get install expect
# MacOs
- script: ci/test.sh
os: osx
before_cache: touch build/osx_test_$TRAVIS_TEST_RESULT
before_script:
- brew install expect

- stage: "Deploy"
# Bionic
Expand All @@ -58,8 +59,6 @@ jobs:
- os: osx
if: tag IS present
script: skip
before_script:
- test -f build/osx_build_0 # Ensure build succeeded
deploy:
- provider: releases
api_key:
Expand Down
15 changes: 15 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,21 @@ if (NOT ELF_INCLUDE_DIRS)
message(FATAL_ERROR "libelf headers not found.")
endif()

# Find 'expect' command required for testing
find_program(FOUND_EXPECT expect DOC "Required for testing.")
if (NOT FOUND_EXPECT)
message(WARNING
"The program 'expect' is not istalled.\n"
"Some tests require this program to be installed and will fail if it is absent.\n"
"However, you can safely build this project without 'expect' being present, as along as you don't need to test it.\n"
"On ubuntu, you should be able to install it using:
sudo apt-get install expect\n"
"On MacOs, you should be able to install it using:
brew install expect\n"
"See more: https://linux.die.net/man/1/expect")
endif()


include_directories(include ./ ${Boost_INCLUDE_DIRS} ${ELF_INCLUDE_DIRS})

# make sure the boost templates compile
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ Requirements:
* boost 1.46 or above
* C++14 GCC or clang
* libelf 0.8.13 or above
* expect 5.45 or above

To build the simulator, run the following commands in the root directory
(assuming `build` is chosen as the build directory):
Expand Down
4 changes: 0 additions & 4 deletions ci/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,3 @@ The scripts should be run in the following order:
- `test`

Running them in a different order or skipping any of them may result in errors.

### `.yml` configs

These are Travis CI configuration files that are loaded by it during tests.
20 changes: 18 additions & 2 deletions include/uart.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include <istream>
#include <ostream>
#include <cstdio>
#include <sys/ioctl.h>

#include "memory-map.h"
#include "exception.h"
Expand Down Expand Up @@ -88,10 +89,25 @@ namespace patmos
// when the input stream reaches the end-of-file (EOF), signal a parity
// error, i.e., PAE = 1.
*value = (1 << TRE);
if (In_stream.rdbuf()->in_avail())
bool any_input;
if (IsTTY) {
// If stream is interactive use ioctl to check
// if there is more input without blocking
auto n = 0;
auto res = ioctl(STDIN_FILENO, FIONREAD, &n);
assert(res == 0);
any_input = n>0;
} else {
// When not interactive, simply peek for next char.
// When peek returns EOF the file or pipe is empty
any_input = EOF != In_stream.peek();
}

if (any_input) {
*value |= (1 << DAV);
else
} else {
*value |= (1 << PAE);
}

return true;
}
Expand Down
7 changes: 3 additions & 4 deletions src/pasim.cc
Original file line number Diff line number Diff line change
Expand Up @@ -333,11 +333,10 @@ void disable_line_buffering()

int main(int argc, char **argv)
{
// the UART simulation may invoke cin.rdbuf()->in_avail(), which does not work
// properly when cin is synced with stdio. we thus disable it here, since we
// are not using stdio anyway.
// We disable line buffering to ensure output is always
// produced immediately. Without this, pasim might exit
// without flushing its output buffer.
disable_line_buffering();
std::cin.sync_with_stdio(false);

// define command-line options
boost::program_options::options_description generic_options(
Expand Down
14 changes: 11 additions & 3 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ Errors : 0")
test_asm(22 "Emitted: 64 bytes
Errors : 0")

test_asm(23 "Emitted: 68 bytes
test_asm(23 "Emitted: 56 bytes
Errors : 0")

test_asm(25 "Emitted: 36 bytes
Expand Down Expand Up @@ -166,13 +166,21 @@ macro (test_io_sim num expr)
# Test input to program through '--in' command line argument
ADD_TEST(sim-test-file-input-${num} ${CMAKE_BINARY_DIR}/src/pasim -V --maxc 40000 --in ${PROJECT_SOURCE_DIR}/tests/test${num}.in ${CMAKE_CURRENT_BINARY_DIR}/test${num}.bin)
SET_TESTS_PROPERTIES(sim-test-file-input-${num} PROPERTIES PASS_REGULAR_EXPRESSION ${expr} DEPENDS asm-test-${num})
# Test input to program through stdin pipe to pasim
# Test input to program through piped stdin
ADD_TEST(sim-test-stdin-input-${num} ${CMAKE_COMMAND}
-DPASIM=${CMAKE_BINARY_DIR}/src/pasim
-DTEST_BIN=${CMAKE_CURRENT_BINARY_DIR}/test${num}.bin
-DINPUT_FILE=${PROJECT_SOURCE_DIR}/tests/test${num}.in
-P ${CMAKE_CURRENT_SOURCE_DIR}/sim-test-stdin-input-cmd.cmake)
SET_TESTS_PROPERTIES(sim-test-stdin-input-${num} PROPERTIES PASS_REGULAR_EXPRESSION ${expr} DEPENDS asm-test-${num})
# Test input to program through interactive stdin
ADD_TEST(sim-test-interactive-stdin-input-${num} expect
${PROJECT_SOURCE_DIR}/tests/sim-test-interactive-stdin-input.sh
--
${CMAKE_BINARY_DIR}/src/pasim
${CMAKE_CURRENT_BINARY_DIR}/test${num}.bin
${PROJECT_SOURCE_DIR}/tests/test${num}.in)
SET_TESTS_PROPERTIES(sim-test-interactive-stdin-input-${num} PROPERTIES PASS_REGULAR_EXPRESSION ${expr} DEPENDS asm-test-${num})
endmacro (test_io_sim)

macro (test_elf_io_sim num expr)
Expand Down Expand Up @@ -244,7 +252,7 @@ test_sim(19 "r1 : 00000007")
test_sim(21 "BASE: 00000004 PC : 0000005c.*
.*r1 : 0000003c")

test_io_sim(22 "r1 : 000000fb")
test_io_sim(22 "r1 : 00000041")

test_sim(23 "!
.*
Expand Down
38 changes: 38 additions & 0 deletions tests/sim-test-interactive-stdin-input.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#!/usr/bin/expect
# This script should be run by Expect and not a shell.
# See: https://linux.die.net/man/1/expect
# It executes pasim, giving it the input specified through stdin
# using an interactive session (not piped, which would not be interactive.)
#
# Takes 3 arguments:
# 1. Path to pasim executable.
# 2. Path to binary program that pasim is to run.
# 3. Path to a file containing the input to pass to pasim's stdin using an interactive session.
#
# Notes:
#
# pasim has 2 seconds to run the program to completion, otherwise this script will
# terminate it.
#
# The output of this script is the stdout of pasim.
#
# The exit code of this script is always 0, regardless of the exit code of pasim.
#
# Example call of this script:
#
# $ expect <script name> -- pasim program.bin input_file

set pasim [lindex $argv 0];
set program [lindex $argv 1];
set input [lindex $argv 2];
# 2 second timeout when this script ends.
set timeout 2

# Spawn program
spawn -noecho $pasim -V --maxc 40000 $program

# Send it some input
send [exec cat $input]

# Send program output to stdout
expect full_buffer
2 changes: 1 addition & 1 deletion tests/test22.in
Original file line number Diff line number Diff line change
@@ -1 +1 @@
A
14 changes: 8 additions & 6 deletions tests/test22.s
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
#
# Expected Result: r1 = 0xfb
# Continualy checks the status flag of the UART until
# it signals there is some input, which is then loaded into r1.
# Expected Result: r1 = 0x41
#

.word 64;
add r1 = r0, 0xF0080000;
addi r2 = r0, 2;
lwl r3 = [r1 + 0];
nop;
nop;
andi r3 = r3, 2;
cmpneq p1 = r3, r2;
(p1) br -3;
(p1) br -4;
nop;
nop;
lwl r1 = [r1 + 1];
halt;
nop;
nop;
nop;
nop;
nop;
nop;
18 changes: 9 additions & 9 deletions tests/test23.s
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
#
# Checks the UART status flag for whether it is ready to
# receive data. If so, the program outputs '!' to the UART
# (which should be seen in stdout.)
# Expected Result: '!' is output, and r2 = 0x21
#

.word 68;
.word 56;
add r1 = r0, 0xF0080000;
addi r2 = r0, 1;
lwl r3 = [r1 + 0];
nop;
nop;
andi r3 = r3, 1;
cmpneq p1 = r3, r2;
(p1) br -3;
(!p1) addi r2 = r0, 0x21;
(!p1) swl [r1 + 1] = r2;
halt;
nop;
nop;
nop;
addi r2 = r0, 0x21;
swl [r1 + 1] = r2;
halt;
nop;
nop;
nop;

0 comments on commit 4d4ec71

Please sign in to comment.