1 // Copyright 2017-2019 VMware, Inc.
2 // SPDX-License-Identifier: BSD-2-Clause
3 //
4 // The BSD-2 license (the License) set forth below applies to all parts of the
5 // Cascade project.  You may not use this file except in compliance with the
6 // License.
7 //
8 // BSD-2 License
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are met:
12 //
13 // 1. Redistributions of source code must retain the above copyright notice, this
14 // list of conditions and the following disclaimer.
15 //
16 // 2. Redistributions in binary form must reproduce the above copyright notice,
17 // this list of conditions and the following disclaimer in the documentation
18 // and/or other materials provided with the distribution.
19 //
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND
21 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 #include <iostream>
32 #include <mutex>
33 #include <ncurses.h>
34 #include <string>
35 #include "cl/cl.h"
36 #include "common/bits.h"
37 #include "target/compiler/remote_compiler.h"
38 #include "target/core/sw/sw_compiler.h"
39 
40 using namespace cascade;
41 using namespace cascade::cl;
42 using namespace std;
43 
44 namespace {
45 
46 __attribute__((unused)) auto& g = Group::create("Software Target Options");
47 auto& port = StrArg<size_t>::create("--port")
48   .usage("<int>")
49   .description("Port to listen for connections on")
50   .initial(8800);
51 auto& path = StrArg<string>::create("--path")
52   .usage("<path/to/socket>")
53   .description("Path to listen for connections on")
54   .initial("/tmp/fpga_socket");
55 
toggle_pad(Bits & pad,mutex & pad_lock,char c)56 void toggle_pad(Bits& pad, mutex& pad_lock, char c) {
57   lock_guard<mutex> lg(pad_lock);
58   pad.flip(c-'1');
59 }
60 
toggle_rst(Bits & rst,mutex & rst_lock)61 void toggle_rst(Bits& rst, mutex& rst_lock) {
62   lock_guard<mutex> lg(rst_lock);
63   rst.flip(0);
64 }
65 
draw_pad(Bits & pad,mutex & pad_lock,int row,int col)66 void draw_pad(Bits& pad, mutex& pad_lock, int row, int col) {
67   lock_guard<mutex> lg(pad_lock);
68   for (int i = 0; i < 4; ++i) {
69     const auto p = pad.get(i) ? '_' : '-';
70     attron(COLOR_PAIR(2));
71     mvprintw((row/2)+1, (col/2)+(2*i)-4, "%c ", p);
72     attroff(COLOR_PAIR(2));
73   }
74 }
75 
draw_rst(Bits & rst,mutex & rst_lock,int row,int col)76 void draw_rst(Bits& rst, mutex& rst_lock, int row, int col) {
77   lock_guard<mutex> lg(rst_lock);
78   const auto r = rst.to_bool() ? '_' : '-';
79   attron(COLOR_PAIR(1));
80   mvprintw((row/2)+1, (col/2)+6, "%c ", r);
81   attroff(COLOR_PAIR(1));
82 }
83 
draw_led(Bits & led,mutex & led_lock,int row,int col)84 void draw_led(Bits& led, mutex& led_lock, int row, int col) {
85   lock_guard<mutex> lg(led_lock);
86   for (int i = 0; i < 8; ++i) {
87     const auto l = led.get(i);
88     const auto cl = l ? 1 : 2;
89     const auto ch = l ? '*' : '.';
90     attron(COLOR_PAIR(cl));
91     mvprintw((row/2)-1, (col/2)+(2*i)-8, "%c ", ch);
92     attroff(COLOR_PAIR(cl));
93   }
94 }
95 
96 } // namespace
97 
main(int argc,char ** argv)98 int main(int argc, char** argv) {
99   // Parse command line:
100   Simple::read(argc, argv);
101 
102   initscr();
103   timeout(1000/40);
104   noecho();
105   curs_set(0);
106   raw();
107   start_color();
108 
109   init_color(COLOR_WHITE, 700, 700, 700);
110   init_pair(1, COLOR_RED, COLOR_BLACK);
111   init_pair(2, COLOR_WHITE, COLOR_BLACK);
112 
113   Bits led(8, 0);
114   Bits pad(4, 0);
115   Bits rst(1, 0);
116 
117   mutex led_lock;
118   mutex pad_lock;
119   mutex rst_lock;
120 
121   auto* rc = new RemoteCompiler();
122   rc->set_path(::path.value());
123   rc->set_port(::port.value());
124   auto* sc = new sw::SwCompiler();
125     sc->set_led(&led, &led_lock);
126     sc->set_pad(&pad, &pad_lock);
127     sc->set_reset(&rst, &rst_lock);
128   rc->set("sw", sc);
129   rc->run();
130 
131   for (auto running = true; running; ) {
132     auto input = getch();
133     switch (input) {
134       case '1':
135       case '2':
136       case '3':
137       case '4':
138         toggle_pad(pad, pad_lock, input);
139         break;
140       case 'r':
141         toggle_rst(rst, rst_lock);
142         break;
143       case 'q':
144         running = false;
145         rc->stop_now();
146         break;
147       default:
148         break;
149     }
150 
151     int row;
152     int col;
153     getmaxyx(stdscr, row, col);
154     draw_pad(pad, pad_lock, row, col);
155     draw_rst(rst, rst_lock, row, col);
156     draw_led(led, led_lock, row, col);
157     refresh();
158   }
159   endwin();
160 
161   delete rc;
162 
163   cout << "Goodbye!" << endl;
164   return 0;
165 }
166