C 32 bit hash_file accessible from tcl for faster hash calculatons

This commit is contained in:
Stefan Frederik 2021-12-10 01:08:31 +01:00
parent 36b8c30fcc
commit deec11851b
5 changed files with 47 additions and 19 deletions

View File

@ -30,6 +30,35 @@ void here(int i)
fprintf(stderr, "here %d\n", i);
}
/* super simple 32 bit hashing function for files
* If you want high collision resistance and
* avoid 'birthday problem' collisions use a better hash function, like md5sum
* or sha256sum
*/
unsigned int hash_file(const char *f)
{
int fd;
int n, i;
unsigned int h=5381;
unsigned char line[4096];
fd = open(f, O_RDONLY);
if(fd >= 0) {
while( (n = read(fd, line, sizeof(line))) ) {
for(i = 0; i < n; i++) {
/* skip CRs so hashes will match on unix / windows */
if(i < n - 1 && line[i] == '\r' && line[i+1] == '\n') continue;
h += (h << 5) + line[i];
}
}
close(fd);
return h;
} else {
fprintf(stderr, "Can not open file %s\n", f);
}
return 0;
}
void set_modify(int mod)
{
char *top_path;

View File

@ -158,7 +158,7 @@ int my_snprintf(char *string, int size, const char *format, ...)
format_spec = 0;
prev = f + 1;
}
else if(format_spec && (*f == 'd' || *f == 'x' || *f == 'c') ) {
else if(format_spec && (*f == 'd' || *f == 'x' || *f == 'c' || *f == 'u') ) {
char nfmt[50], nstr[50];
int i, nlen;
i = va_arg(args, int);

View File

@ -1133,7 +1133,19 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
}
else if(argv[1][0] == 'h') {
if(!strcmp(argv[1],"help"))
if(!strcmp(argv[1],"hash_file"))
{
unsigned int h;
char s[40];
cmd_found = 1;
if(argc > 2) {
h = hash_file(argv[2]);
my_snprintf(s, S(s), "%u", h);
Tcl_SetResult(interp, s, TCL_VOLATILE);
}
}
else if(!strcmp(argv[1],"help"))
{
cmd_found = 1;
xschem_cmd_help(argc, argv);
@ -1694,7 +1706,6 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
else if(!strcmp(argv[1],"paste"))
{
xRect boundbox;
cmd_found = 1;
merge_file(2,".sch");
if(argc > 3) {

View File

@ -887,6 +887,7 @@ extern void set_grid(double);
extern void create_plot_cmd(void);
extern void set_modify(int mod);
extern void dbg(int level, char *fmt, ...);
extern unsigned int hash_file(const char *f);
extern void here(int i);
extern void print_version(void);
extern int set_netlist_dir(int force, char *dir);

View File

@ -7,6 +7,7 @@
## - logic simulation engine
## - print png, svg, pdf
## - trim wires
## - copy/paste operations
## run:
# xschem --script /path/to/drawtest.tcl
## optionally with logging to catch memory leaks:
@ -18,20 +19,6 @@
## calculate 32 bit hash of file, used to compare files.
## This is NOT a crypto hash, and NOT even a strong collision resistant hash
## but for our purposes this is enough
proc hash_file {f} {
set hash 5381
set fd [open $f r]
fconfigure $fd -encoding binary -translation binary
set data [read $fd]
## hash should be the same on windows: remove carriage returns
regsub -all {\r} $data {} data
close $fd
for {set i 0} {$i < [string length $data]} {incr i} {
set asciicode [scan [string index $data $i] %c]
set hash [expr {($hash * 33 + $asciicode) & 0xffffffff}]
}
return $hash
}
## move schematic and redraw in a loop.
proc drawtest {} {
@ -160,13 +147,13 @@ proc xschemtest {{view 0}} {
foreach {f h} {
greycnt.v 389394682
mos_power_ampli.spice 1186348644
autozero_comp.spice 1416313184
autozero_comp.spice 2011673313
loading.vhdl 3834408538
LCC_instances.spice 3918341865
simulate_ff.spice 1321596936
rom8k.spice 2198713988
} {
if { [hash_file $netlist_dir/$f] == $h } {
if { [xschem hash_file $netlist_dir/$f] == $h } {
puts "$f netlist check OK"
} else {
puts "$f netlist check FAIL"