Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/port access #164

Merged
merged 11 commits into from
Nov 30, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ execute_process(COMMAND git describe --tags
message(STATUS "Version: ${GIT_DESCRIBE_RESULT}")
string(STRIP "${GIT_DESCRIBE_RESULT}" ION_KIT_VERSION_S)
add_definitions("-DION_KIT_VERSION=\"${ION_KIT_VERSION_S}\"")
string(REPLACE "v" "" ION_KIT_VERSION ${ION_KIT_VERSION_S})
string(REPLACE "v" "" ION_KIT_VERSION "${ION_KIT_VERSION_S}")
file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/VERSION CONTENT "${ION_KIT_VERSION_S}")

#
Expand Down
29 changes: 21 additions & 8 deletions include/ion/port.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,15 +147,15 @@ class Port {
friend class Node;

Port()
: key_(), type_(), dimensions_(0), node_id_(), param_info_() {}
: key_(), type_(), dimensions_(0), index_(-1), node_id_(), param_info_() {}

/**
* Construct new port for scalar value.
* @arg k: The key of the port which should be matched with BuildingBlock Input/Output name.
* @arg t: The type of the value.
*/
Port(const std::string& k, Halide::Type t)
: key_(k), type_(t), dimensions_(0), node_id_(), param_info_(new ParamContainer(k, t)) {}
: key_(k), type_(t), dimensions_(0), index_(-1), node_id_(), param_info_(new ParamContainer(k, t)) {}

/**
* Construct new port for vector value.
Expand All @@ -164,7 +164,7 @@ class Port {
* @arg d: The dimension of the port. The range is 1 to 4.
*/
Port(const std::string& k, Halide::Type t, int32_t d)
: key_(k), type_(t), dimensions_(d), node_id_(), param_info_(new ParamContainer(k, t, d)) {}
: key_(k), type_(t), dimensions_(d), index_(-1), node_id_(), param_info_(new ParamContainer(k, t, d)) {}

std::string key() const { return key_; }
std::string& key() { return key_; }
Expand All @@ -175,6 +175,9 @@ class Port {
int32_t dimensions() const { return dimensions_; }
int32_t& dimensions() { return dimensions_; }

int32_t index() const { return index_; }
int32_t& index() { return index_; }

std::string node_id() const { return node_id_; }
std::string& node_id() { return node_id_; }

Expand Down Expand Up @@ -203,15 +206,25 @@ class Port {
return !node_id_.empty();
}

private:
/**
* This port is bound with some node.
*/
Port(const std::string& k, const std::string& ni) : key_(k), type_(), dimensions_(0), node_id_(ni), param_info_(nullptr){}

/**
* Overloaded operator to set the port index and return a reference to the current port. eg. port[0]
*/
Port operator[](int i) {
this->index_ = i;
return *this;
}

private:
/**
* This port is bound with some node.
*/
Port(const std::string& k, const std::string& ni) : key_(k), type_(), index_(-1), dimensions_(0), node_id_(ni), param_info_(nullptr){}

std::string key_;
Halide::Type type_;
int32_t dimensions_;
int32_t index_;
std::string node_id_;
std::shared_ptr<ParamContainer> param_info_;
};
Expand Down
6 changes: 4 additions & 2 deletions src/bb/base/rt.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,12 @@ namespace bb {
namespace base {

std::tuple<std::string, std::string> parse_url(const std::string &url) {
if (url.rfind("http://", 0) != 0) { // not starts_with
auto protocol_end_pos = url.find("://");
if (protocol_end_pos == std::string::npos) {
return std::tuple<std::string, std::string>("", "");
}
auto path_name_pos = url.find("/", 7);
auto host_name_pos = protocol_end_pos + 3;
auto path_name_pos = url.find("/", host_name_pos);
auto host_name = url.substr(0, path_name_pos);
auto path_name = url.substr(path_name_pos);
return std::tuple<std::string, std::string>(host_name, path_name);
Expand Down
162 changes: 162 additions & 0 deletions src/bb/image-io/bb.h
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,164 @@ class Camera : public ion::BuildingBlock<Camera> {
}
};

class Camera2 : public ion::BuildingBlock<Camera2> {
public:
GeneratorParam<int32_t> num_devices{"num_devices", 2};
GeneratorParam<std::string> gc_title{"gc_title", "USBCamera"};
GeneratorParam<std::string> gc_description{"gc_description", "This captures USB camera image."};
GeneratorParam<std::string> gc_tags{"gc_tags", "input,sensor"};
GeneratorParam<std::string> gc_inference{"gc_inference", R"((function(v){ return { output: [parseInt(v.width), parseInt(v.height), 3] }}))"};
GeneratorParam<std::string> gc_mandatory{"gc_mandatory", "width,height"};
GeneratorParam<std::string> gc_strategy{"gc_strategy", "self"};
GeneratorParam<std::string> gc_prefix{"gc_prefix", ""};

GeneratorParam<int32_t> fps{"fps", 30};
GeneratorParam<int32_t> width{"width", 0};
GeneratorParam<int32_t> height{"height", 0};
GeneratorParam<int32_t> index{"index", 0};
GeneratorParam<std::string> url0{"url0", ""};
GeneratorParam<std::string> url1{"url1", ""};



GeneratorOutput<Halide::Func> output0{"output0", Halide::type_of<uint8_t>(), 3};
GeneratorOutput<Halide::Func> output1{"output1", Halide::type_of<uint8_t>(), 3};


void generate() {
using namespace Halide;


for (int i =0; i < num_devices; i++){
std::string url_str;
if(i == 0){
url_str = url0;
}
else{
url_str = url1;
}

Halide::Buffer<uint8_t> url_buf(url_str.size() + 1);
url_buf.fill(0);
std::memcpy(url_buf.data(), url_str.c_str(), url_str.size());

std::vector<ExternFuncArgument> params = {instance_id++, cast<int32_t>(index), cast<int32_t>(fps), cast<int32_t>(width), cast<int32_t>(height), url_buf};
Func camera(static_cast<std::string>(gc_prefix) + "camera");
camera.define_extern("ion_bb_image_io_camera", params, Halide::type_of<uint8_t>(), 2);
camera.compute_root();

Func camera_ = BoundaryConditions::repeat_edge(camera, {{0, 2 * width}, {0, height}});

Var c, x, y;

Expr yv = cast<float>(camera_(2 * x, y));
Expr uv = cast<float>(camera_(select((x & 1) == 0, 2 * x + 1, 2 * x - 1), y));
Expr vv = cast<float>(camera_(select((x & 1) == 0, 2 * x + 3, 2 * x + 1), y));

Expr f128 = cast<float>(128);
Expr r = saturating_cast<uint8_t>(yv + cast<float>(1.403f) * (vv - f128));
Expr g = saturating_cast<uint8_t>(yv - cast<float>(0.344f) * (uv - f128) - (cast<float>(0.714f) * (vv - f128)));
Expr b = saturating_cast<uint8_t>(yv + cast<float>(1.773f) * (uv - f128));




Func f(static_cast<std::string>(gc_prefix) + "output" + std::to_string(i));
f(x, y, c) = mux(c, {r, g, b});


if (i ==0)
output0 = f;
else
output1 = f;
}

}
};



class CameraN : public ion::BuildingBlock<CameraN> {
public:
GeneratorParam<int32_t> num_devices{"num_devices", 2};
GeneratorParam<std::string> gc_title{"gc_title", "USBCamera"};
GeneratorParam<std::string> gc_description{"gc_description", "This captures USB camera image."};
GeneratorParam<std::string> gc_tags{"gc_tags", "input,sensor"};
GeneratorParam<std::string> gc_inference{"gc_inference", R"((function(v){ return { output: [parseInt(v.width), parseInt(v.height), 3] }}))"};
GeneratorParam<std::string> gc_mandatory{"gc_mandatory", "width,height"};
GeneratorParam<std::string> gc_strategy{"gc_strategy", "self"};
GeneratorParam<std::string> gc_prefix{"gc_prefix", ""};

GeneratorParam<int32_t> fps{"fps", 30};
GeneratorParam<int32_t> width{"width", 0};
GeneratorParam<int32_t> height{"height", 0};
GeneratorParam<int32_t> index{"index", 0};
GeneratorParam<std::string> urls{"urls", ""};

// GeneratorInput<Buffer<uint8_t>[]> urls{"urls"};
GeneratorOutput<Halide::Func[]> output{"output", Halide::type_of<uint8_t>(), 3};


void generate() {

std::stringstream urls_stream(urls);
std::string url;
std::vector<std::string> url_list;
while(std::getline(urls_stream, url, ';'))
{
url_list.push_back(url);
}


using namespace Halide;

output.resize(num_devices);

for (int i =0; i < num_devices; i++){
std::string url_str;
if (url_list.size()!=0){
url_str = url_list[i];
}
else{
url_str = "";
}



Halide::Buffer<uint8_t> url_buf(url_str.size() + 1);
url_buf.fill(0);
std::memcpy(url_buf.data(), url_str.c_str(), url_str.size());

std::vector<ExternFuncArgument> params = {instance_id++, cast<int32_t>(index), cast<int32_t>(fps), cast<int32_t>(width), cast<int32_t>(height), url_buf};
Func camera(static_cast<std::string>(gc_prefix) + "camera");
camera.define_extern("ion_bb_image_io_camera", params, Halide::type_of<uint8_t>(), 2);
camera.compute_root();

Func camera_ = BoundaryConditions::repeat_edge(camera, {{0, 2 * width}, {0, height}});

Var c, x, y;

Expr yv = cast<float>(camera_(2 * x, y));
Expr uv = cast<float>(camera_(select((x & 1) == 0, 2 * x + 1, 2 * x - 1), y));
Expr vv = cast<float>(camera_(select((x & 1) == 0, 2 * x + 3, 2 * x + 1), y));

Expr f128 = cast<float>(128);
Expr r = saturating_cast<uint8_t>(yv + cast<float>(1.403f) * (vv - f128));
Expr g = saturating_cast<uint8_t>(yv - cast<float>(0.344f) * (uv - f128) - (cast<float>(0.714f) * (vv - f128)));
Expr b = saturating_cast<uint8_t>(yv + cast<float>(1.773f) * (uv - f128));


Func f(static_cast<std::string>(gc_prefix) + "output" + std::to_string(i));
f(x, y, c) = mux(c, {r, g, b});

output[i](_) = f(_);
}

}
};



class GenericV4L2Bayer : public ion::BuildingBlock<GenericV4L2Bayer> {
public:
GeneratorParam<std::string> gc_title{"gc_title", "GenericV4L2Bayer"};
Expand Down Expand Up @@ -1087,7 +1245,11 @@ class BinaryLoader : public ion::BuildingBlock<BinaryLoader> {
#ifndef _WIN32
ION_REGISTER_BUILDING_BLOCK(ion::bb::image_io::IMX219, image_io_imx219);
ION_REGISTER_BUILDING_BLOCK(ion::bb::image_io::D435, image_io_d435);

ION_REGISTER_BUILDING_BLOCK(ion::bb::image_io::Camera, image_io_camera);
ION_REGISTER_BUILDING_BLOCK(ion::bb::image_io::Camera2, image_io_camera2);
ION_REGISTER_BUILDING_BLOCK(ion::bb::image_io::CameraN, image_io_cameraN);

ION_REGISTER_BUILDING_BLOCK(ion::bb::image_io::GenericV4L2Bayer, image_io_generic_v4l2_bayer);
ION_REGISTER_BUILDING_BLOCK(ion::bb::image_io::CameraSimulation, image_io_camera_simulation);
ION_REGISTER_BUILDING_BLOCK(ion::bb::image_io::FBDisplay, image_io_fb_display);
Expand Down
9 changes: 5 additions & 4 deletions src/bb/image-io/rt_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,11 @@ class DynamicModule {
};

std::tuple<std::string, std::string> parse_url(const std::string &url) {
if (url.rfind("http://", 0) != 0) { // not starts_with
auto protocol_end_pos = url.find("://");
if (protocol_end_pos == std::string::npos)
return std::tuple<std::string, std::string>("", "");
}
auto path_name_pos = url.find("/", 7);
auto host_name_pos = protocol_end_pos + 3;
auto path_name_pos = url.find("/", host_name_pos);
auto host_name = url.substr(0, path_name_pos);
auto path_name = url.substr(path_name_pos);
return std::tuple<std::string, std::string>(host_name, path_name);
Expand Down Expand Up @@ -329,4 +330,4 @@ struct rawHeader {
} // namespace bb
} // namespace ion

#endif
#endif
15 changes: 14 additions & 1 deletion src/builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ Halide::Pipeline Builder::build(const ion::PortMap& pm, std::vector<Halide::Buff
std::vector<std::vector<Internal::StubInput>> args;
for (size_t j=0; j<n.ports().size(); ++j) {
auto p = n.ports()[j];
auto index = p.index();
// Unbounded parameter
auto *in = bb->param_info().inputs().at(j);
if (p.node_id().empty()) {
Expand Down Expand Up @@ -308,7 +309,19 @@ Halide::Pipeline Builder::build(const ion::PortMap& pm, std::vector<Halide::Buff
}
args.push_back(bb->build_input(j, f()));
} else if (in->kind() == Internal::IOKind::Function) {
args.push_back(bb->build_input(j, f));
auto fs =bbs[p.node_id()]->get_outputs(p.key());
// no specific index provided, direct output Port
if (index == -1)
args.push_back(bb->build_input(j,f));
else{
// access to Port[index]
if (index>=fs.size()){
throw std::runtime_error("Port index out of range: " + in->name());
}
args.push_back(bb->build_input(j, fs[index]));
}


} else {
throw std::runtime_error("fixme");
}
Expand Down
6 changes: 6 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ ion_jit(port-binding SRCS port-binding.cc)
add_dependencies(port-binding ion-bb-test)
ion_register_test(port-binding_test port-binding)

# Port index access
ion_jit(port-access SRCS port-access.cc)
add_dependencies(port-access ion-bb-test)
ion_register_test(port-access_test port-access)


ion_jit(direct-extern SRCS direct-extern.cc)
add_dependencies(direct-extern ion-bb-test)
ion_register_test(direct-extern_test direct-extern)
Expand Down
Loading
Loading