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 #ifndef CASCADE_SRC_TARGET_COMPILER_H
32 #define CASCADE_SRC_TARGET_COMPILER_H
33 
34 #include <mutex>
35 #include <set>
36 #include <string>
37 #include <unordered_map>
38 #include <unordered_set>
39 #include "runtime/runtime.h"
40 #include "verilog/ast/ast_fwd.h"
41 #include "verilog/ast/visitors/visitor.h"
42 
43 namespace cascade {
44 
45 class CoreCompiler;
46 class Engine;
47 class Interface;
48 
49 class Compiler {
50   public:
51     Compiler();
52     virtual ~Compiler();
53 
54     // Configuration Interface:
55     //
56     // These methods are not thread-safe. The results on invoking these methods
57     // after the first invocation of compile() or to replace a previously
58     // registered compiler are undefined.
59     Compiler& set(const std::string& id, CoreCompiler* c);
60     CoreCompiler* get(const std::string& id);
61 
62     // Compilation Interface:
63     //
64     // These methods are all thread-safe and return immediately.
65     //
66     // Ignores md and returns an engine backed by a StubCore.  This method does
67     // not take ownership of md and is undefined for modules with incompatible
68     // __loc annotations.
69     Engine* compile_stub(Engine::Id id, const ModuleDeclaration* md);
70     // Compiles md using the core compiler specified by the __target
71     // annotation.  This method takes ownership of md.
72     Engine* compile(Engine::Id id, ModuleDeclaration* md);
73     // Causes all invocations of compile() associated with id to return in a
74     // *reasonably short* amount of time. If an invocation of compile() would
75     // return normally it may do so, otherwise, it will return nullptr.
76     void stop_compile(Engine::Id id);
77     // Causes all invocations of compile() to return in a *reasonably short*
78     // amount of time. If an invocation of compile() would return normally it
79     // may do so, otherwise, it will return nullptr.
80     void stop_compile();
81     // Invokes stop_async() on all registered compilers.
82     void stop_async();
83 
84     // Error Reporting Interface:
85     //
86     // These methods are all thread safe and report errors if any in-flight
87     // compilations encountered an error.
88     void error(const std::string& s);
89     void fatal(const std::string& s);
90     bool error();
91     std::pair<bool, std::string> what();
92     void clear();
93 
94     // Scheduling Interface:
95     //
96     // Schedules a blocking interrupt in a state safe window defined by all
97     // registered compilers. This method is thread safe, but should only be
98     // invoked by second-pass jit-compilers. Invoking this method in a first-
99     // pass compiler will cause the runtime to hang.
100     virtual void schedule_state_safe_interrupt(Runtime::Interrupt int_) = 0;
101 
102   protected:
103     // Interface Compilation... Interface:
104     //
105     // Sanity checks the __loc annotation on a module declaration and returns
106     // either the interface provided by this compiler or nullptr.
107     virtual Interface* get_interface(const std::string& loc) = 0;
108 
109   private:
110     // Checks whether a module is a stub: a module with no inputs or outputs,
111     // and no runtime-visible side-effects.
112     class StubCheck : public Visitor {
113       public:
114         ~StubCheck() override = default;
115         bool check(const ModuleDeclaration* md);
116       private:
117         bool stub_;
118         void visit(const InitialConstruct* ic) override;
119         void visit(const FinishStatement* fs) override;
120         void visit(const RestartStatement* rs) override;
121         void visit(const RetargetStatement* rs) override;
122         void visit(const SaveStatement* ss) override;
123     };
124 
125     // Compilers:
126     std::unordered_map<std::string, CoreCompiler*> ccs_;
127 
128     // Compilation State:
129     std::unordered_set<Engine::Id> ids_;
130 
131     // Error State:
132     std::mutex lock_;
133     bool fatal_;
134     std::string what_;
135 };
136 
137 } // namespace cascade
138 
139 #endif
140