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 "target/core/sw/sw_compiler.h"
32 
33 #include "target/compiler.h"
34 #include "verilog/analyze/evaluate.h"
35 #include "verilog/analyze/module_info.h"
36 #include "verilog/analyze/resolve.h"
37 #include "verilog/ast/ast.h"
38 
39 using namespace std;
40 
41 namespace cascade::sw {
42 
SwCompiler()43 SwCompiler::SwCompiler() : CoreCompiler() {
44   set_led(nullptr, nullptr);
45   set_pad(nullptr, nullptr);
46   set_reset(nullptr, nullptr);
47 }
48 
set_led(Bits * b,mutex * l)49 SwCompiler& SwCompiler::set_led(Bits* b, mutex* l) {
50   led_ = b;
51   led_lock_ = l;
52   return *this;
53 }
54 
set_pad(Bits * b,mutex * l)55 SwCompiler& SwCompiler::set_pad(Bits* b, mutex* l) {
56   pad_ = b;
57   pad_lock_ = l;
58   return *this;
59 }
60 
set_reset(Bits * b,mutex * l)61 SwCompiler& SwCompiler::set_reset(Bits* b, mutex* l) {
62   reset_ = b;
63   reset_lock_ = l;
64   return *this;
65 }
66 
stop_compile(Engine::Id id)67 void SwCompiler::stop_compile(Engine::Id id) {
68   // Does nothing. Compilations all return in a reasonable amount of time.
69   (void) id;
70 }
71 
compile_clock(Engine::Id id,ModuleDeclaration * md,Interface * interface)72 SwClock* SwCompiler::compile_clock(Engine::Id id, ModuleDeclaration* md, Interface* interface) {
73   (void) id;
74 
75   if (!check_io(md, 0, 1)) {
76     get_compiler()->error("Unable to compile a software clock with more than one output");
77     delete md;
78     return nullptr;
79   }
80 
81   const auto* out = *ModuleInfo(md).outputs().begin();
82   const auto oid = to_vid(out);
83   delete md;
84 
85   return new SwClock(interface, oid);
86 }
87 
compile_led(Engine::Id id,ModuleDeclaration * md,Interface * interface)88 SwLed* SwCompiler::compile_led(Engine::Id id, ModuleDeclaration* md, Interface* interface) {
89   (void) id;
90 
91   if (led_ == nullptr) {
92     get_compiler()->error("Unable to compile a software led without a reference to a software fpga");
93     delete md;
94     return nullptr;
95   }
96   if (!check_io(md, 8, 8)) {
97     get_compiler()->error("Unable to compile a software led with more than 8 outputs");
98     delete md;
99     return nullptr;
100   }
101 
102   if (!ModuleInfo(md).inputs().empty()) {
103     const auto* in = *ModuleInfo(md).inputs().begin();
104     const auto iid = to_vid(in);
105     const auto w = Evaluate().get_width(in);
106     delete md;
107     return new SwLed(interface, iid, w, led_, led_lock_);
108   } else {
109     delete md;
110     return new SwLed(interface, nullid(), 0, led_, led_lock_);
111   }
112 }
113 
compile_logic(Engine::Id id,ModuleDeclaration * md,Interface * interface)114 SwLogic* SwCompiler::compile_logic(Engine::Id id, ModuleDeclaration* md, Interface* interface) {
115   (void) id;
116 
117   ModuleInfo info(md);
118   auto* c = new SwLogic(interface, md);
119   for (auto* i : info.inputs()) {
120     c->set_input(i, to_vid(i));
121   }
122   for (auto* s : info.stateful()) {
123     c->set_state(s, to_vid(s));
124   }
125   for (auto* o : info.outputs()) {
126     c->set_output(o, to_vid(o));
127   }
128   return c;
129 }
130 
compile_pad(Engine::Id id,ModuleDeclaration * md,Interface * interface)131 SwPad* SwCompiler::compile_pad(Engine::Id id, ModuleDeclaration* md, Interface* interface) {
132   (void) id;
133 
134   if (pad_ == nullptr) {
135     get_compiler()->error("Unable to compile a software pad without a reference to a software fpga");
136     delete md;
137     return nullptr;
138   }
139   if (pad_ == nullptr || !check_io(md, 0, 4)) {
140     get_compiler()->error("Unable to compile a software pad with more than four inputs");
141     delete md;
142     return nullptr;
143   }
144 
145   const auto* out = *ModuleInfo(md).outputs().begin();
146   const auto oid = to_vid(out);
147   const auto w = Evaluate().get_width(out);
148   delete md;
149 
150   return new SwPad(interface, oid, w, pad_, pad_lock_);
151 }
152 
compile_reset(Engine::Id id,ModuleDeclaration * md,Interface * interface)153 SwReset* SwCompiler::compile_reset(Engine::Id id, ModuleDeclaration* md, Interface* interface) {
154   (void) id;
155 
156   if (pad_ == nullptr) {
157     get_compiler()->error("Unable to compile a software reset without a reference to a software fpga");
158     delete md;
159     return nullptr;
160   }
161   if (pad_ == nullptr || !check_io(md, 0, 1)) {
162     get_compiler()->error("Unable to compile a software reset with more than one input");
163     delete md;
164     return nullptr;
165   }
166 
167   const auto* out = *ModuleInfo(md).outputs().begin();
168   const auto oid = to_vid(out);
169   delete md;
170 
171   return new SwReset(interface, oid, reset_, reset_lock_);
172 }
173 
174 } // namespace cascade::sw
175