mirror of
https://github.com/YosysHQ/yosys
synced 2025-08-02 17:30:24 +00:00
WIP
This commit is contained in:
parent
aa5b7075cb
commit
f75add5912
2 changed files with 110 additions and 32 deletions
|
@ -5,6 +5,7 @@
|
|||
#include <tcl.h>
|
||||
#include <list>
|
||||
#include <regex>
|
||||
#include <optional>
|
||||
|
||||
|
||||
USING_YOSYS_NAMESPACE
|
||||
|
@ -12,10 +13,11 @@ PRIVATE_NAMESPACE_BEGIN
|
|||
|
||||
|
||||
struct SdcObjects {
|
||||
enum GetterMode {
|
||||
Simple,
|
||||
Full
|
||||
} mode;
|
||||
enum CollectMode {
|
||||
SimpleGetter,
|
||||
FullGetter,
|
||||
FullConstraint,
|
||||
} collect_mode;
|
||||
std::vector<std::string> design_ports;
|
||||
std::vector<std::pair<std::string, Cell*>> design_cells;
|
||||
std::vector<std::pair<std::string, Cell*>> design_pins;
|
||||
|
@ -90,26 +92,26 @@ struct SdcObjects {
|
|||
constrained_cells.sort();
|
||||
constrained_pins.sort();
|
||||
constrained_nets.sort();
|
||||
log("Design ports:\n");
|
||||
for (auto name : design_ports) {
|
||||
log("\t%s\n", name.c_str());
|
||||
}
|
||||
log("Design cells:\n");
|
||||
for (auto [name, cell] : design_cells) {
|
||||
(void)cell;
|
||||
log("\t%s\n", name.c_str());
|
||||
}
|
||||
log("Design pins:\n");
|
||||
for (auto [name, pin] : design_pins) {
|
||||
(void)pin;
|
||||
log("\t%s\n", name.c_str());
|
||||
}
|
||||
log("Design nets:\n");
|
||||
for (auto [name, net] : design_nets) {
|
||||
(void)net;
|
||||
log("\t%s\n", name.c_str());
|
||||
}
|
||||
log("\n");
|
||||
// log("Design ports:\n");
|
||||
// for (auto name : design_ports) {
|
||||
// log("\t%s\n", name.c_str());
|
||||
// }
|
||||
// log("Design cells:\n");
|
||||
// for (auto [name, cell] : design_cells) {
|
||||
// (void)cell;
|
||||
// log("\t%s\n", name.c_str());
|
||||
// }
|
||||
// log("Design pins:\n");
|
||||
// for (auto [name, pin] : design_pins) {
|
||||
// (void)pin;
|
||||
// log("\t%s\n", name.c_str());
|
||||
// }
|
||||
// log("Design nets:\n");
|
||||
// for (auto [name, net] : design_nets) {
|
||||
// (void)net;
|
||||
// log("\t%s\n", name.c_str());
|
||||
// }
|
||||
// log("\n");
|
||||
log("Constrained ports:\n");
|
||||
for (auto name : constrained_ports) {
|
||||
log("\t%s\n", name.c_str());
|
||||
|
@ -169,7 +171,6 @@ static bool matches(std::string name, const std::string& pat, const MatchConfig&
|
|||
|
||||
static int sdc_get_pins_cmd(ClientData data, Tcl_Interp *interp, int objc, Tcl_Obj* const objv[])
|
||||
{
|
||||
(void)interp;
|
||||
auto* objects = (SdcObjects*)data;
|
||||
// When this flag is present, the search for the pattern is made in all positions in the hierarchy.
|
||||
bool hierarchical_flag = false;
|
||||
|
@ -198,7 +199,7 @@ static int sdc_get_pins_cmd(ClientData data, Tcl_Interp *interp, int objc, Tcl_O
|
|||
for (; i < objc; i++) {
|
||||
patterns.push_back(Tcl_GetString(objv[i]));
|
||||
}
|
||||
if (objects->mode == SdcObjects::GetterMode::Simple) {
|
||||
if (objects->collect_mode == SdcObjects::CollectMode::SimpleGetter) {
|
||||
if (regexp_flag || hierarchical_flag || nocase_flag || separator != "/" || of_objects) {
|
||||
log_error("get_pins got unexpected flags in simple mode\n");
|
||||
}
|
||||
|
@ -210,7 +211,6 @@ static int sdc_get_pins_cmd(ClientData data, Tcl_Interp *interp, int objc, Tcl_O
|
|||
MatchConfig config(regexp_flag, nocase_flag, hierarchical_flag);
|
||||
std::vector<std::pair<std::string, Cell*>> resolved;
|
||||
for (auto pat : patterns) {
|
||||
log("get_pins sniffs %s\n", pat.c_str());
|
||||
bool found = false;
|
||||
for (auto [name, pin] : objects->design_pins) {
|
||||
if (matches(name, pat, config)) {
|
||||
|
@ -224,7 +224,8 @@ static int sdc_get_pins_cmd(ClientData data, Tcl_Interp *interp, int objc, Tcl_O
|
|||
Tcl_Obj *result = Tcl_NewListObj(resolved.size(), nullptr);
|
||||
for (auto obj : resolved) {
|
||||
Tcl_ListObjAppendElement(interp, result, Tcl_NewStringObj(obj.first.c_str(), obj.first.size()));
|
||||
objects->constrained_pins.insert(obj);
|
||||
if (objects->collect_mode != SdcObjects::CollectMode::FullConstraint)
|
||||
objects->constrained_pins.insert(obj);
|
||||
}
|
||||
|
||||
if (separator != "/") {
|
||||
|
@ -238,7 +239,6 @@ static int sdc_get_pins_cmd(ClientData data, Tcl_Interp *interp, int objc, Tcl_O
|
|||
|
||||
static int sdc_get_ports_cmd(ClientData data, Tcl_Interp *interp, int objc, Tcl_Obj* const objv[])
|
||||
{
|
||||
(void)interp;
|
||||
auto* objects = (SdcObjects*)data;
|
||||
bool regexp_flag = false;
|
||||
bool nocase_flag = false;
|
||||
|
@ -253,7 +253,7 @@ static int sdc_get_ports_cmd(ClientData data, Tcl_Interp *interp, int objc, Tcl_
|
|||
for (; i < objc; i++) {
|
||||
patterns.push_back(Tcl_GetString(objv[i]));
|
||||
}
|
||||
if (objects->mode == SdcObjects::GetterMode::Simple) {
|
||||
if (objects->collect_mode == SdcObjects::CollectMode::SimpleGetter) {
|
||||
if (regexp_flag || nocase_flag) {
|
||||
log_error("get_ports got unexpected flags in simple mode\n");
|
||||
}
|
||||
|
@ -277,13 +277,89 @@ static int sdc_get_ports_cmd(ClientData data, Tcl_Interp *interp, int objc, Tcl_
|
|||
Tcl_Obj *result = Tcl_NewListObj(resolved.size(), nullptr);
|
||||
for (auto obj : resolved) {
|
||||
Tcl_ListObjAppendElement(interp, result, Tcl_NewStringObj(obj.c_str(), obj.size()));
|
||||
objects->constrained_ports.insert(obj);
|
||||
if (objects->collect_mode != SdcObjects::CollectMode::FullConstraint)
|
||||
objects->constrained_ports.insert(obj);
|
||||
}
|
||||
|
||||
Tcl_SetObjResult(interp, result);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
std::optional<std::tuple<std::string, std::string>> split_at(std::string s)
|
||||
{
|
||||
size_t pos = s.find('@');
|
||||
if (pos == std::string::npos)
|
||||
return std::nullopt;
|
||||
return std::make_tuple(s.substr(0, pos), s.substr(pos + 1));
|
||||
}
|
||||
|
||||
// Whether string or list of strings, apply op to each string
|
||||
void apply_args(Tcl_Interp *interp, std::function<void(const char*)> op, Tcl_Obj* obj)
|
||||
{
|
||||
int length;
|
||||
Tcl_Obj **value_list;
|
||||
if (Tcl_ListObjGetElements(interp, obj, &length, &value_list) == TCL_OK) {
|
||||
for (int i = 0; i < length; i++) {
|
||||
op(Tcl_GetString(value_list[i]));
|
||||
}
|
||||
} else {
|
||||
op(Tcl_GetString(obj));
|
||||
}
|
||||
}
|
||||
|
||||
static int ys_track_typed_key_cmd(ClientData data, Tcl_Interp *interp, int objc, Tcl_Obj* const objv[])
|
||||
{
|
||||
log("ys_track_typed_key_cmd\n");
|
||||
auto* objects = (SdcObjects*)data;
|
||||
if (objc != 5)
|
||||
log_error("ys_track_typed_key: Unexpected number of arguments: %d (expected 5)\n", objc);
|
||||
|
||||
if (objects->collect_mode != SdcObjects::CollectMode::FullConstraint)
|
||||
return TCL_OK;
|
||||
|
||||
std::string key_name = Tcl_GetString(objv[1]);
|
||||
Tcl_Obj* key_value = objv[2];
|
||||
std::string key_expect_type = Tcl_GetString(objv[3]);
|
||||
std::string proc_name = Tcl_GetString(objv[4]);
|
||||
|
||||
auto track_typed = [key_expect_type, objects, proc_name, key_name](const char* str) -> void {
|
||||
auto split = split_at(str);
|
||||
if (!split)
|
||||
log_error("%s: key %s should be a typed SDC object, but is something weird: %s\n",
|
||||
proc_name.c_str(), key_name.c_str(), str);
|
||||
|
||||
if (key_expect_type == "pin") {
|
||||
log("PIN! %s\n", str);
|
||||
bool found = false;
|
||||
for (auto [name, pin] : objects->design_pins) {
|
||||
if (name + "/" + pin->name.str() == str) {
|
||||
found = true;
|
||||
objects->constrained_pins.insert(std::make_pair(name, pin));
|
||||
break; // resolved, expected unique
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
log_error("%s: pin %s not found\n", proc_name.c_str(), str);
|
||||
} else if (key_expect_type == "port") {
|
||||
bool found = false;
|
||||
for (auto name : objects->design_ports) {
|
||||
if (name == str) {
|
||||
found = true;
|
||||
objects->constrained_ports.insert(name);
|
||||
break; // resolved, expected unique
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
log_error("%s: port %s not found\n", proc_name.c_str(), str);
|
||||
} else {
|
||||
// TODO
|
||||
log_warning("%s: unsupported type %s\n", proc_name.c_str(), key_expect_type.c_str());
|
||||
}
|
||||
};
|
||||
apply_args(interp, track_typed, key_value);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
||||
class SDCInterpreter
|
||||
{
|
||||
|
@ -308,8 +384,10 @@ public:
|
|||
log_error("Tcl_Init() call failed - %s\n",Tcl_ErrnoMsg(Tcl_GetErrno()));
|
||||
|
||||
objects = std::make_unique<SdcObjects>(design);
|
||||
objects->collect_mode = SdcObjects::CollectMode::FullConstraint;
|
||||
Tcl_CreateObjCommand(interp, "get_pins", sdc_get_pins_cmd, (ClientData) objects.get(), NULL);
|
||||
Tcl_CreateObjCommand(interp, "get_ports", sdc_get_ports_cmd, (ClientData) objects.get(), NULL);
|
||||
Tcl_CreateObjCommand(interp, "ys_track_typed_key", ys_track_typed_key_cmd, (ClientData) objects.get(), NULL);
|
||||
return interp;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -15,7 +15,7 @@ proc get_clocks {args} {
|
|||
}
|
||||
|
||||
stub current_design
|
||||
stub ys_track_typed_key
|
||||
#stub ys_track_typed_key
|
||||
stub ys_track_untyped_key
|
||||
stub ys_err_key
|
||||
stub ys_err_flag
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue