17 #include <unordered_set>
35 std::filesystem::path gate_definitions_path = verilator_sim_path /
"gate_definitions/";
36 std::filesystem::create_directory(gate_definitions_path);
37 std::set<std::string> provided_models;
38 if (!model_path.empty())
44 for (
auto& it : gate_type_names)
47 if (provided_models.find(it.first->get_name()) != provided_models.end())
49 log_debug(
"verilator",
"using provided model for gate: {}", it.first->get_name());
53 bool replace_name =
false;
54 if (it.second == it.first->get_name())
56 log_info(
"verilator",
"creating verilog simulation model for '{}'", it.first->get_name());
60 log_info(
"verilator",
"creating verilog simulation model for '{}' which corresponds to gate type '{}'", it.second, it.first->get_name());
63 std::stringstream gate_description;
70 if (gate_function.empty())
72 log_error(
"verilator",
"unimplemented reached: gate type: '{}', cannot create simulation model...", it.first->get_name());
75 gate_description << gate_function << std::endl;
81 std::ofstream gate_file(gate_definitions_path / (it.second +
".v"));
84 std::string buffer = gate_description.str();
88 pos = buffer.find(it.first->get_name());
89 if (pos == std::string::npos)
93 buffer.replace(pos, it.first->get_name().size(), it.second);
94 pos += it.second.size();
100 gate_file << gate_description.str();
108 std::set<std::string>
get_provided_models(
const std::filesystem::path model_path,
const std::filesystem::path gate_definition_path)
110 std::set<std::string> supported_gate_types;
111 if (!std::filesystem::exists(model_path))
113 log_warning(
"verilator",
"provided_models path '{}' does not exist", model_path.string());
114 return supported_gate_types;
116 for (
const auto& entry : std::filesystem::directory_iterator(model_path))
118 std::string file = entry.path().filename();
120 if (entry.path().extension() !=
".v")
122 log_info(
"verilator",
"not reading {} from simulation path, since it is not verilog (no .v extension)", file);
127 supported_gate_types.insert(file);
130 std::filesystem::copy(entry.path(), gate_definition_path);
133 if (!supported_gate_types.empty())
135 log_info(
"verilator",
"using provided gate simulation models for: ");
136 for (
const auto& gate : supported_gate_types)
138 log_info(
"verilator",
"\t{}", gate);
143 log_info(
"verilator",
"no gate types were provided");
146 return supported_gate_types;
151 std::unordered_map<GateType*, std::string> gate_types;
155 gate_types.emplace(std::make_pair<GateType*, std::string>(gate->get_type(),
get_name_for_gate_type(gate->get_type())));
163 std::stringstream retval;
168 if (isdigit(cc) && retval.str().empty())
180 retval << '_' << std::hex << static_cast<unsigned int>(cc) <<
"_";
188 std::stringstream prologue;
190 prologue <<
"`timescale 1 ps/1 ps" << std::endl;
191 prologue <<
"module " << gt->
get_name() << std::endl;
195 if (!gate_params.empty())
197 prologue <<
"#(" << std::endl;
198 std::string parameter_str;
199 for (
const auto& [
name, param] : gate_params)
201 const u32 size = param.get_size();
202 std::string hex_default = param.get_default_value();
203 if (hex_default.size() >= 2 && hex_default[0] ==
'0' && (hex_default[1] ==
'x' || hex_default[1] ==
'X'))
204 hex_default = hex_default.substr(2);
205 if (hex_default.empty())
206 hex_default = std::string(std::max(1u,
size / 4),
'0');
207 std::stringstream entry;
208 entry <<
"\tparameter [" <<
size - 1 <<
":0] " <<
name <<
" = " <<
size <<
"'h"
209 << std::setfill(
'0') << std::setw(std::max(1u,
size / 4)) << hex_default <<
",\n";
210 parameter_str += entry.str();
212 parameter_str.erase(parameter_str.find_last_of(
","));
213 prologue << parameter_str << std::endl;
214 prologue <<
")" << std::endl;
218 prologue <<
"(" << std::endl;
220 std::unordered_set<GatePin*> visited_pins;
221 for (
const auto pin : gt->
get_pins())
224 if (visited_pins.find(pin) != visited_pins.end())
232 if (
const auto* pin_group = pin->get_group().first; pin_group !=
nullptr)
234 const auto group_pins = pin_group->get_pins();
235 prologue <<
" [" << std::to_string(pin_group->get_index(group_pins.back()).get()) <<
":" << std::to_string(pin_group->get_index(group_pins.front()).get()) <<
"] "
236 << pin_group->get_name() <<
"," << std::endl;
238 for (
const auto pin : group_pins)
240 visited_pins.insert(pin);
246 prologue << pin->get_name() <<
"," << std::endl;
250 prologue.seekp(-2, prologue.cur);
252 prologue << std::endl;
253 prologue <<
");" << std::endl;
254 prologue << std::endl;
256 return prologue.str();
263 return ERR(
"node arity of " + std::to_string(node.
get_arity()) +
" does not match number of operands of " + std::to_string(operands.size()));
270 for (
const auto& value : node.
constant)
274 return OK(std::to_string(node.
constant.size()) +
"'b" + str);
277 return OK(std::to_string(node.
index));
281 return OK(
"(" + operands[0] +
" & " + operands[1] +
")");
283 return OK(
"(! " + operands[0] +
")");
285 return OK(
"(" + operands[0] +
" | " + operands[1] +
")");
287 return OK(
"(" + operands[0] +
" ^ " + operands[1] +
")");
289 return ERR(
"unsupported node type '" + std::to_string(node.
type) +
"'");
295 std::stringstream gate_description;
317 return gate_description.str();
322 std::stringstream epilogue;
324 epilogue <<
"endmodule" << std::endl;
326 return epilogue.str();
std::string get_name() const
const std::string & get_name() const
bool has_property(GateTypeProperty property) const
const std::unordered_map< std::string, Parameter > & get_parameters() const
std::vector< GatePin * > get_pins(const std::function< bool(GatePin *)> &filter=nullptr) const
const std::vector< Gate * > & get_gates() const
const GateLibrary * get_gate_library() const
#define log_error(channel,...)
#define log_debug(channel,...)
#define log_info(channel,...)
#define log_warning(channel,...)
T replace(const T &str, const T &search, const T &replace)
bool convert_gate_library_to_verilog(const Netlist *nl, const std::filesystem::path verilator_sim_path, const std::filesystem::path model_path="")
std::string get_function_for_latch(const GateType *gt)
std::string get_prologue_for_gate_type(const GateType *gt)
std::string get_function_for_ff(const GateType *gt)
std::string get_function_for_lut(const GateType *gt)
Result< std::string > verilog_function_printer(const BooleanFunction::Node &node, std::vector< std::string > &&operands)
std::string get_function_for_combinational_gate(const GateType *gt)
std::unordered_map< GateType *, std::string > get_gate_gate_types_from_netlist(const Netlist *nl)
std::string get_function_for_gate(const GateType *gt)
std::set< std::string > get_provided_models(const std::filesystem::path model_path, const std::filesystem::path gate_definition_path)
std::string get_epilogue_for_gate_type()
std::string get_name_for_gate_type(const GateType *gt)
std::string enum_to_string(T e)
std::vector< BooleanFunction::Value > constant
The (optional) constant value of the node.
u16 type
The type of the node.
std::string variable
The (optional) variable name of the node.
u16 index
The (optional) index value of the node.
static constexpr u16 Constant
static constexpr u16 Index
static constexpr u16 Variable