36 std::filesystem::path gate_definitions_path = verilator_sim_path /
"gate_definitions/";
37 std::filesystem::create_directory(gate_definitions_path);
38 std::set<std::string> provided_models;
39 if (!model_path.empty())
45 for (
auto& it : gate_type_names)
48 if (provided_models.find(it.first->get_name()) != provided_models.end())
50 log_debug(
"verilator",
"using provided model for gate: {}", it.first->get_name());
54 bool replace_name =
false;
55 if (it.second == it.first->get_name())
56 log_info(
"verilator",
"creating verilog simulation model for '{}'", it.first->get_name());
59 log_info(
"verilator",
"creating verilog simulation model for '{}' which corresponds to gate type '{}'",
60 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)
break;
90 buffer.replace(pos, it.first->get_name().size(), it.second);
91 pos += it.second.size();
96 gate_file << gate_description.str();
103 std::set<std::string>
get_provided_models(
const std::filesystem::path model_path,
const std::filesystem::path gate_definition_path)
105 std::set<std::string> supported_gate_types;
106 if (!std::filesystem::exists(model_path))
108 log_warning(
"verilator",
"provided_models path '{}' does not exist", model_path.string());
109 return supported_gate_types;
111 for (
const auto& entry : std::filesystem::directory_iterator(model_path))
113 std::string file = entry.path().filename();
115 if (entry.path().extension() !=
".v")
117 log_info(
"verilator",
"not reading {} from simulation path, since it is not verilog (no .v extension)", file);
122 supported_gate_types.insert(file);
125 std::filesystem::copy(entry.path(), gate_definition_path);
128 if (!supported_gate_types.empty())
130 log_info(
"verilator",
"using provided gate simulation models for: ");
131 for (
const auto& gate : supported_gate_types)
133 log_info(
"verilator",
"\t{}", gate);
138 log_info(
"verilator",
"no gate types were provided");
141 return supported_gate_types;
146 std::unordered_map<GateType*,std::string> gate_types;
150 gate_types.emplace(std::make_pair<GateType*,std::string>(gate->get_type(),
get_name_for_gate_type(gate->get_type())));
158 std::stringstream retval;
163 if (isdigit(cc) && retval.str().empty())
171 retval << '_' << std::hex << static_cast<unsigned int>(cc) <<
"_";
179 std::vector<std::string> parameters;
184 u32 init_len = 1 << lut_size;
185 bool lut_init_descending =
false;
189 if (!lut_component->is_init_ascending())
191 lut_init_descending =
true;
196 log_error(
"verilator",
"cannot get LUTComponent, aborting...");
197 return std::vector<std::string>();
200 std::stringstream parameter;
204 if (init_component ==
nullptr)
206 log_error(
"verilator",
"Could not get init component for gate type {}!", gt->
get_name());
209 if (lut_init_descending)
211 parameter <<
"parameter [" << init_len - 1 <<
":0]"
212 <<
" " << init_component->
get_init_identifiers().front() <<
" = " << init_len <<
"'h" << std::setfill(
'0') << std::setw(init_len / 4) << 0 <<
",";
216 parameter <<
"parameter [0:" << init_len - 1 <<
"]"
217 <<
" " << init_component->
get_init_identifiers().front() <<
" = " << init_len <<
"'h" << std::setfill(
'0') << std::setw(init_len / 4) << 0 <<
",";
220 parameters.push_back(parameter.str());
226 std::stringstream parameter;
227 parameter <<
"parameter [0:0]"
228 <<
" " << init_component->get_init_identifiers().front() <<
"= 1'b0,";
229 parameters.push_back(parameter.str());
238 std::stringstream prologue;
240 prologue <<
"`timescale 1 ps/1 ps" << std::endl;
242 prologue <<
"module " << gt->
get_name() << std::endl;
249 if (!parameters.empty())
251 prologue <<
"#(" << std::endl;
252 std::string parameter_str;
253 for (
const auto& parameter : parameters)
255 parameter_str +=
"\t" + parameter +
"\n";
257 parameter_str.erase(parameter_str.find_last_of(
","));
258 prologue << parameter_str << std::endl;
259 prologue <<
")" << std::endl;
263 prologue <<
"(" << std::endl;
265 std::unordered_set<GatePin*> visited_pins;
266 for (
const auto pin : gt->
get_pins())
269 if (visited_pins.find(pin) != visited_pins.end())
277 if (
const auto* pin_group = pin->get_group().first; pin_group !=
nullptr)
279 const auto group_pins = pin_group->get_pins();
280 prologue <<
" [" << std::to_string(pin_group->get_index(group_pins.back()).get()) <<
":" << std::to_string(pin_group->get_index(group_pins.front()).get()) <<
"] "
281 << pin_group->get_name() <<
"," << std::endl;
283 for (
const auto pin : group_pins)
285 visited_pins.insert(pin);
291 prologue << pin->get_name() <<
"," << std::endl;
295 prologue.seekp(-2, prologue.cur);
297 prologue << std::endl;
298 prologue <<
");" << std::endl;
299 prologue << std::endl;
301 return prologue.str();
308 return ERR(
"node arity of " + std::to_string(node.
get_arity()) +
" does not match number of operands of " + std::to_string(operands.size()));
315 for (
const auto& value : node.
constant)
319 return OK(std::to_string(node.
constant.size()) +
"'b" + str);
322 return OK(std::to_string(node.
index));
326 return OK(
"(" + operands[0] +
" & " + operands[1] +
")");
328 return OK(
"(! " + operands[0] +
")");
330 return OK(
"(" + operands[0] +
" | " + operands[1] +
")");
332 return OK(
"(" + operands[0] +
" ^ " + operands[1] +
")");
334 return ERR(
"unsupported node type '" + std::to_string(node.
type) +
"'");
340 std::stringstream gate_description;
362 return gate_description.str();
367 std::stringstream epilogue;
369 epilogue <<
"endmodule" << std::endl;
371 return epilogue.str();
std::string get_name() const
const std::string & get_name() const
bool has_property(GateTypeProperty property) const
std::vector< GatePin * > get_input_pins() const
T * get_component_as(const std::function< bool(const GateTypeComponent *)> &filter=nullptr) const
std::vector< GatePin * > get_pins(const std::function< bool(GatePin *)> &filter=nullptr) const
static bool is_class_of(const GateTypeComponent *component)
const std::vector< std::string > & get_init_identifiers() 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::vector< std::string > get_parameters_for_gate(const GateType *gt)
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