mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-04 05:19:11 +00:00 
			
		
		
		
	sdc: separate out
This commit is contained in:
		
							parent
							
								
									38145e79dd
								
							
						
					
					
						commit
						b749906b9a
					
				
					 5 changed files with 117 additions and 86 deletions
				
			
		| 
						 | 
				
			
			@ -533,64 +533,6 @@ static int tcl_set_param(ClientData, Tcl_Interp *interp, int objc, Tcl_Obj *cons
 | 
			
		|||
	return TCL_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int sdc_get_pins_cmd(ClientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
 | 
			
		||||
{
 | 
			
		||||
	(void)interp;
 | 
			
		||||
	bool hierarchical_flag = false;
 | 
			
		||||
	bool regexp_flag = false;
 | 
			
		||||
	bool nocase_flag = false;
 | 
			
		||||
	std::string separator = "/";
 | 
			
		||||
	Tcl_Obj* of_objects;
 | 
			
		||||
	std::vector<std::string> patterns;
 | 
			
		||||
	int i = 1;
 | 
			
		||||
	for (; i < objc; i++) {
 | 
			
		||||
		FLAG2(hierarchical)
 | 
			
		||||
		FLAG2(regexp)
 | 
			
		||||
		FLAG2(nocase)
 | 
			
		||||
		if (!strcmp(Tcl_GetString(objv[i]), "-hsc")) {
 | 
			
		||||
			i++;
 | 
			
		||||
			separator = Tcl_GetString(objv[i]);
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		if (!strcmp(Tcl_GetString(objv[i]), "-of_objects")) {
 | 
			
		||||
			i++;
 | 
			
		||||
			of_objects = objv[i];
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		// Onto the next loop
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	for (; i < objc; i++) {
 | 
			
		||||
		patterns.push_back(Tcl_GetString(objv[i]));
 | 
			
		||||
	}
 | 
			
		||||
	log("get_pins patterns:\n");
 | 
			
		||||
	for (auto pat : patterns) {
 | 
			
		||||
		log("\t%s\n", pat.c_str());
 | 
			
		||||
	}
 | 
			
		||||
	(void)hierarchical_flag;
 | 
			
		||||
	(void)regexp_flag;
 | 
			
		||||
	(void)nocase_flag;
 | 
			
		||||
	(void)separator;
 | 
			
		||||
	(void)of_objects;
 | 
			
		||||
	return TCL_OK;
 | 
			
		||||
}
 | 
			
		||||
static int sdc_dummy_cmd(ClientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
 | 
			
		||||
{
 | 
			
		||||
	(void)interp;
 | 
			
		||||
	(void)objc;
 | 
			
		||||
	log("Ignoring known SDC command %s\n", Tcl_GetString(objv[0]));
 | 
			
		||||
	return TCL_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int yosys_sdc_interp_init(Tcl_Interp *interp)
 | 
			
		||||
{
 | 
			
		||||
	if (Tcl_Init(interp)!=TCL_OK)
 | 
			
		||||
		log_warning("Tcl_Init() call failed - %s\n",Tcl_ErrnoMsg(Tcl_GetErrno()));
 | 
			
		||||
	Tcl_CreateObjCommand(interp, "set_false_path", sdc_dummy_cmd, NULL, NULL);
 | 
			
		||||
	Tcl_CreateObjCommand(interp, "get_pins", sdc_get_pins_cmd, NULL, NULL);
 | 
			
		||||
	return TCL_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int yosys_tcl_interp_init(Tcl_Interp *interp)
 | 
			
		||||
{
 | 
			
		||||
	if (Tcl_Init(interp)!=TCL_OK)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -370,7 +370,6 @@ void rewrite_filename(std::string &filename)
 | 
			
		|||
 | 
			
		||||
// defined in tclapi.cc
 | 
			
		||||
extern int yosys_tcl_interp_init(Tcl_Interp *interp);
 | 
			
		||||
extern int yosys_sdc_interp_init(Tcl_Interp *interp);
 | 
			
		||||
 | 
			
		||||
extern Tcl_Interp *yosys_get_tcl_interp()
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -380,15 +379,8 @@ extern Tcl_Interp *yosys_get_tcl_interp()
 | 
			
		|||
	}
 | 
			
		||||
	return yosys_tcl_interp;
 | 
			
		||||
}
 | 
			
		||||
extern Tcl_Interp *yosys_get_sdc_interp()
 | 
			
		||||
{
 | 
			
		||||
	if (yosys_sdc_interp == NULL) {
 | 
			
		||||
		yosys_sdc_interp = Tcl_CreateInterp();
 | 
			
		||||
		yosys_sdc_interp_init(yosys_sdc_interp);
 | 
			
		||||
	}
 | 
			
		||||
	return yosys_sdc_interp;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Also see SdcPass
 | 
			
		||||
struct TclPass : public Pass {
 | 
			
		||||
	TclPass() : Pass("tcl", "execute a TCL script file") { }
 | 
			
		||||
	void help() override {
 | 
			
		||||
| 
						 | 
				
			
			@ -431,26 +423,7 @@ struct TclPass : public Pass {
 | 
			
		|||
		Tcl_Release(interp);
 | 
			
		||||
	}
 | 
			
		||||
} TclPass;
 | 
			
		||||
struct SdcPass : public Pass {
 | 
			
		||||
	SdcPass() : Pass("sdc", "sniff at some SDC") { }
 | 
			
		||||
	void execute(std::vector<std::string> args, RTLIL::Design *) override {
 | 
			
		||||
		if (args.size() < 2)
 | 
			
		||||
			log_cmd_error("Missing script file.\n");
 | 
			
		||||
 | 
			
		||||
		std::vector<Tcl_Obj*> script_args;
 | 
			
		||||
		for (auto it = args.begin() + 2; it != args.end(); ++it)
 | 
			
		||||
			script_args.push_back(Tcl_NewStringObj((*it).c_str(), (*it).size()));
 | 
			
		||||
 | 
			
		||||
		Tcl_Interp *interp = yosys_get_sdc_interp();
 | 
			
		||||
		Tcl_Preserve(interp);
 | 
			
		||||
		Tcl_ObjSetVar2(interp, Tcl_NewStringObj("argc", 4), NULL, Tcl_NewIntObj(script_args.size()), 0);
 | 
			
		||||
		Tcl_ObjSetVar2(interp, Tcl_NewStringObj("argv", 4), NULL, Tcl_NewListObj(script_args.size(), script_args.data()), 0);
 | 
			
		||||
		Tcl_ObjSetVar2(interp, Tcl_NewStringObj("argv0", 5), NULL, Tcl_NewStringObj(args[1].c_str(), args[1].size()), 0);
 | 
			
		||||
		if (Tcl_EvalFile(interp, args[1].c_str()) != TCL_OK)
 | 
			
		||||
			log_cmd_error("SDC interpreter returned an error: %s\n", Tcl_GetStringResult(interp));
 | 
			
		||||
		Tcl_Release(interp);
 | 
			
		||||
	}
 | 
			
		||||
} SdcPass;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(__linux__) || defined(__CYGWIN__)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -57,3 +57,6 @@ OBJS += passes/cmds/abstract.o
 | 
			
		|||
OBJS += passes/cmds/test_select.o
 | 
			
		||||
OBJS += passes/cmds/timeest.o
 | 
			
		||||
OBJS += passes/cmds/linecoverage.o
 | 
			
		||||
OBJS += passes/cmds/sdc.o
 | 
			
		||||
 | 
			
		||||
$(eval $(call add_share_file,share/sdc,passes/cmds/stubs.sdc))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										112
									
								
								passes/cmds/sdc.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								passes/cmds/sdc.cc
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,112 @@
 | 
			
		|||
#include "kernel/register.h"
 | 
			
		||||
#include "kernel/celltypes.h"
 | 
			
		||||
#include "kernel/rtlil.h"
 | 
			
		||||
#include "kernel/log.h"
 | 
			
		||||
#include <tcl.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
USING_YOSYS_NAMESPACE
 | 
			
		||||
PRIVATE_NAMESPACE_BEGIN
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
static bool parse_flag(char* arg, const char* flag_name, T& flag_var) {
 | 
			
		||||
    std::string expected = std::string("-") + flag_name;
 | 
			
		||||
    if (expected == arg) {
 | 
			
		||||
        flag_var = true;
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int sdc_get_pins_cmd(ClientData, Tcl_Interp *interp, int objc, Tcl_Obj* const objv[])
 | 
			
		||||
{
 | 
			
		||||
	(void)interp;
 | 
			
		||||
	bool hierarchical_flag = false;
 | 
			
		||||
	bool regexp_flag = false;
 | 
			
		||||
	bool nocase_flag = false;
 | 
			
		||||
	std::string separator = "/";
 | 
			
		||||
	Tcl_Obj* of_objects;
 | 
			
		||||
	std::vector<std::string> patterns;
 | 
			
		||||
	int i = 1;
 | 
			
		||||
	for (; i < objc; i++) {
 | 
			
		||||
        if (parse_flag(Tcl_GetString(objv[i]), "hierarchical", hierarchical_flag))
 | 
			
		||||
        if (parse_flag(Tcl_GetString(objv[i]), "regexp", regexp_flag)) continue;
 | 
			
		||||
        if (parse_flag(Tcl_GetString(objv[i]), "nocase", nocase_flag)) continue;
 | 
			
		||||
		if (!strcmp(Tcl_GetString(objv[i]), "-hsc")) {
 | 
			
		||||
			separator = Tcl_GetString(objv[++i]);
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		if (!strcmp(Tcl_GetString(objv[i]), "-of_objects")) {
 | 
			
		||||
			of_objects = objv[++i];
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		// Onto the next loop
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	for (; i < objc; i++) {
 | 
			
		||||
		patterns.push_back(Tcl_GetString(objv[i]));
 | 
			
		||||
	}
 | 
			
		||||
	log("get_pins patterns:\n");
 | 
			
		||||
	for (auto pat : patterns) {
 | 
			
		||||
		log("\t%s\n", pat.c_str());
 | 
			
		||||
	}
 | 
			
		||||
	(void)hierarchical_flag;
 | 
			
		||||
	(void)regexp_flag;
 | 
			
		||||
	(void)nocase_flag;
 | 
			
		||||
	(void)separator;
 | 
			
		||||
	(void)of_objects;
 | 
			
		||||
	return TCL_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class SDCInterpreter
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
    Tcl_Interp* interp = nullptr;
 | 
			
		||||
public:
 | 
			
		||||
    ~SDCInterpreter() {
 | 
			
		||||
        if (interp)
 | 
			
		||||
            Tcl_DeleteInterp(interp);
 | 
			
		||||
    }
 | 
			
		||||
    static SDCInterpreter& get() {
 | 
			
		||||
        static SDCInterpreter instance;
 | 
			
		||||
        return instance;
 | 
			
		||||
    }
 | 
			
		||||
    Tcl_Interp* fresh_interp() {
 | 
			
		||||
        if (interp)
 | 
			
		||||
            Tcl_DeleteInterp(interp);
 | 
			
		||||
        interp = Tcl_CreateInterp();
 | 
			
		||||
        if (Tcl_Init(interp)!=TCL_OK)
 | 
			
		||||
            log_warning("Tcl_Init() call failed - %s\n",Tcl_ErrnoMsg(Tcl_GetErrno()));
 | 
			
		||||
        Tcl_CreateObjCommand(interp, "get_pins", sdc_get_pins_cmd, NULL, NULL);
 | 
			
		||||
        return interp;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Also see TclPass
 | 
			
		||||
struct SdcPass : public Pass {
 | 
			
		||||
	SdcPass() : Pass("sdc", "sniff at some SDC") { }
 | 
			
		||||
	void execute(std::vector<std::string> args, RTLIL::Design *) override {
 | 
			
		||||
		if (args.size() < 2)
 | 
			
		||||
			log_cmd_error("Missing script file.\n");
 | 
			
		||||
 | 
			
		||||
		std::vector<Tcl_Obj*> script_args;
 | 
			
		||||
		for (auto it = args.begin() + 2; it != args.end(); ++it)
 | 
			
		||||
			script_args.push_back(Tcl_NewStringObj((*it).c_str(), (*it).size()));
 | 
			
		||||
 | 
			
		||||
		Tcl_Interp *interp = SDCInterpreter::get().fresh_interp();
 | 
			
		||||
		Tcl_Preserve(interp);
 | 
			
		||||
		Tcl_ObjSetVar2(interp, Tcl_NewStringObj("argc", 4), NULL, Tcl_NewIntObj(script_args.size()), 0);
 | 
			
		||||
		Tcl_ObjSetVar2(interp, Tcl_NewStringObj("argv", 4), NULL, Tcl_NewListObj(script_args.size(), script_args.data()), 0);
 | 
			
		||||
		Tcl_ObjSetVar2(interp, Tcl_NewStringObj("argv0", 5), NULL, Tcl_NewStringObj(args[1].c_str(), args[1].size()), 0);
 | 
			
		||||
 | 
			
		||||
        std::string stub_path = "+/sdc/stubs.sdc";
 | 
			
		||||
        rewrite_filename(stub_path);
 | 
			
		||||
		if (Tcl_EvalFile(interp, stub_path.c_str()) != TCL_OK)
 | 
			
		||||
            log_cmd_error("SDC interpreter returned an error in stub file: %s\n", Tcl_GetStringResult(interp));
 | 
			
		||||
		if (Tcl_EvalFile(interp, args[1].c_str()) != TCL_OK)
 | 
			
		||||
			log_cmd_error("SDC interpreter returned an error: %s\n", Tcl_GetStringResult(interp));
 | 
			
		||||
		Tcl_Release(interp);
 | 
			
		||||
	}
 | 
			
		||||
} SdcPass;
 | 
			
		||||
 | 
			
		||||
YOSYS_NAMESPACE_END
 | 
			
		||||
							
								
								
									
										1
									
								
								passes/cmds/stubs.sdc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								passes/cmds/stubs.sdc
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
proc set_false_path {args} {}
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue