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