Skip to content

Commit e1c9b44

Browse files
committedJun 4, 2017
Began work on loading timing data from JSON
1 parent 57950d4 commit e1c9b44

9 files changed

+355
-27
lines changed
 

Diff for: ‎src/gp4tchar/main.cpp

+71-6
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ using namespace std;
2828

2929
DevkitCalibration g_devkitCal;
3030

31+
bool LoadTimingData(string fname);
32+
3133
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3234
// Entry point
3335

@@ -120,19 +122,25 @@ int main(int argc, char* argv[])
120122
return 1;
121123
}
122124

123-
//Measure delay through each element
124-
if(!MeasurePinToPinDelays(sock, hdev))
125+
//Load timing data from disk
126+
LogNotice("Loading timing data...\n");
127+
string tfname = "timing.json";
128+
if(!LoadTimingData(tfname))
125129
return 1;
130+
131+
//Measure delay through each element
132+
//if(!MeasurePinToPinDelays(sock, hdev))
133+
// return 1;
126134
//if(!MeasureCrossConnectionDelays(sock, hdev))
127135
// return 1;
128136
//if(!MeasureLutDelays(sock, hdev))
129137
// return 1;
130138

131139
//Save to disk
132-
string fout = "timing.json";
133-
LogNotice("Saving timing data to file %s\n", fout.c_str());
134-
g_calDevice.SaveTimingData(fout.c_str());
135-
140+
/*
141+
LogNotice("Saving timing data to file %s\n", tfname.c_str());
142+
g_calDevice.SaveTimingData(tfname.c_str());
143+
*/
136144
//Print output
137145
LogNotice("Dumping timing data...\n");
138146
{
@@ -149,6 +157,63 @@ int main(int argc, char* argv[])
149157
return 0;
150158
}
151159

160+
bool LoadTimingData(string fname)
161+
{
162+
//Open the file (non-existence is a legal no-op, return success silently)
163+
FILE* fp = fopen(fname.c_str(), "rb");
164+
if(fp == NULL)
165+
return true;
166+
if(0 != fseek(fp, 0, SEEK_END))
167+
{
168+
LogError("Failed to seek to end of timing data file %s\n", fname.c_str());
169+
fclose(fp);
170+
return false;
171+
}
172+
size_t len = ftell(fp);
173+
if(0 != fseek(fp, 0, SEEK_SET))
174+
{
175+
LogError("Failed to seek to start of timing data file %s\n", fname.c_str());
176+
return false;
177+
}
178+
char* json_string = new char[len + 1];
179+
json_string[len] = '\0';
180+
if(len != fread(json_string, 1, len, fp))
181+
{
182+
LogError("Failed to read contents of timing data file %s\n", fname.c_str());
183+
delete[] json_string;
184+
fclose(fp);
185+
return false;
186+
}
187+
fclose(fp);
188+
189+
//Parse the JSON
190+
json_tokener* tok = json_tokener_new();
191+
if(!tok)
192+
{
193+
LogError("Failed to create JSON tokenizer object\n");
194+
delete[] json_string;
195+
return false;
196+
}
197+
json_tokener_error err;
198+
json_object* object = json_tokener_parse_verbose(json_string, &err);
199+
if(NULL == object)
200+
{
201+
const char* desc = json_tokener_error_desc(err);
202+
LogError("JSON parsing failed (err = %s)\n", desc);
203+
delete[] json_string;
204+
return false;
205+
}
206+
207+
//Load stuff
208+
if(!g_calDevice.LoadTimingData(object))
209+
return false;
210+
211+
//Done
212+
json_object_put(object);
213+
json_tokener_free(tok);
214+
return true;
215+
}
216+
152217
void WaitForKeyPress()
153218
{
154219
LogNotice("Press any key to continue . . .\n");

Diff for: ‎src/gp4tchar/measurements.cpp

-3
Original file line numberDiff line numberDiff line change
@@ -364,9 +364,6 @@ bool MeasurePinToPinDelays(Socket& sock, hdevice hdev)
364364
iob->SetOutputDelay(Greenpak4IOB::DRIVE_1X, corner, CombinatorialDelay(obuf_x1.m_value, -1));
365365
iob->SetOutputDelay(Greenpak4IOB::DRIVE_2X, corner, CombinatorialDelay(obuf_x2.m_value, -1));
366366
}
367-
368-
//DEBUG
369-
return true;
370367
}
371368
}
372369

Diff for: ‎src/greenpak4/Greenpak4BitstreamEntity.cpp

+152
Original file line numberDiff line numberDiff line change
@@ -372,3 +372,155 @@ void Greenpak4BitstreamEntity::SaveTimingData(FILE* fp, PTVCorner corner)
372372
fprintf(fp, " },\n");
373373
}
374374
}
375+
376+
/**
377+
@brief Load our delay info
378+
*/
379+
bool Greenpak4BitstreamEntity::LoadTimingData(json_object* object)
380+
{
381+
for(int i=0; i<json_object_array_length(object); i++)
382+
{
383+
auto child = json_object_array_get_idx(object, i);
384+
if(!LoadTimingDataForCorner(child))
385+
return false;
386+
}
387+
388+
return true;
389+
}
390+
391+
/**
392+
@brief Loads delay info for a single process-corner object in the JSON file
393+
*/
394+
bool Greenpak4BitstreamEntity::LoadTimingDataForCorner(json_object* object)
395+
{
396+
//Look up the corner info
397+
json_object* process;
398+
if(!json_object_object_get_ex(object, "process", &process))
399+
{
400+
LogError("No process info for this corner\n");
401+
return false;
402+
}
403+
string sprocess = json_object_get_string(process);
404+
405+
json_object* temp;
406+
if(!json_object_object_get_ex(object, "temp", &temp))
407+
{
408+
LogError("No temp info for this corner\n");
409+
return false;
410+
}
411+
int ntemp = json_object_get_int(temp);
412+
413+
json_object* voltage;
414+
if(!json_object_object_get_ex(object, "voltage_mv", &voltage))
415+
{
416+
LogError("No voltage info for this corner\n");
417+
return false;
418+
}
419+
int nvoltage = json_object_get_int(voltage);
420+
421+
//TODO: move this into PTVCorner class?
422+
PTVCorner::ProcessSpeed speed;
423+
if(sprocess == "fast")
424+
speed = PTVCorner::SPEED_FAST;
425+
else if(sprocess == "slow")
426+
speed = PTVCorner::SPEED_SLOW;
427+
else if(sprocess == "typical")
428+
speed = PTVCorner::SPEED_TYPICAL;
429+
430+
//This is the process corner we're loading
431+
PTVCorner corner(speed, ntemp, nvoltage);
432+
433+
//This is the actual timing data!
434+
json_object* delays;
435+
if(!json_object_object_get_ex(object, "delays", &delays))
436+
{
437+
LogError("No delay info for this corner\n");
438+
return false;
439+
}
440+
441+
//Now that we know where to put it, we can load the actual timing data
442+
for(int i=0; i<json_object_array_length(delays); i++)
443+
{
444+
auto child = json_object_array_get_idx(delays, i);
445+
446+
//We need to know the type of delay. "propagation" is handled by us
447+
//Anything else is a derived class
448+
json_object* type;
449+
if(!json_object_object_get_ex(child, "type", &type))
450+
{
451+
LogError("No type info for this delay value\n");
452+
return false;
453+
}
454+
string stype = json_object_get_string(type);
455+
456+
//Load rising/falling delays and save them
457+
if(stype == "propagation")
458+
{
459+
if(!LoadPropagationDelay(corner, child))
460+
return false;
461+
continue;
462+
}
463+
464+
//Nope, something special
465+
if(!LoadExtraTimingData(corner, stype, child))
466+
return false;
467+
}
468+
469+
return true;
470+
}
471+
472+
/**
473+
@brief Loads propagation delay for a single endpoint and process corner
474+
*/
475+
bool Greenpak4BitstreamEntity::LoadPropagationDelay(PTVCorner corner, json_object* object)
476+
{
477+
//Pull out all of the json stuff
478+
json_object* from;
479+
if(!json_object_object_get_ex(object, "from", &from))
480+
{
481+
LogError("No source for this delay\n");
482+
return false;
483+
}
484+
string sfrom = json_object_get_string(from);
485+
486+
json_object* to;
487+
if(!json_object_object_get_ex(object, "to", &to))
488+
{
489+
LogError("No dest for this delay\n");
490+
return false;
491+
}
492+
string sto = json_object_get_string(to);
493+
494+
json_object* rising;
495+
if(!json_object_object_get_ex(object, "rising", &rising))
496+
{
497+
LogError("No rising info for this corner\n");
498+
return false;
499+
}
500+
float nrising = json_object_get_double(rising);
501+
502+
json_object* falling;
503+
if(!json_object_object_get_ex(object, "falling", &falling))
504+
{
505+
LogError("No falling info for this corner\n");
506+
return false;
507+
}
508+
float nfalling = json_object_get_double(falling);
509+
510+
//Finally, we can actually save the delay!
511+
m_pinToPinDelays[corner][PinPair(sfrom, sto)] = CombinatorialDelay(nrising, nfalling);
512+
513+
return true;
514+
}
515+
516+
/**
517+
@brief Loads timing data other than normal propagation info
518+
519+
Base class implementation should never be called (base class should override) if there's any extra data,
520+
but we need a default implementation to avoid every derived class having an empty stub
521+
*/
522+
bool Greenpak4BitstreamEntity::LoadExtraTimingData(PTVCorner /*corner*/, string /*delaytype*/, json_object* /*object*/)
523+
{
524+
LogWarning("Greenpak4BitstreamEntity: Don't know what to do with delay type %s\n", delaytype.c_str());
525+
return true;
526+
}

Diff for: ‎src/greenpak4/Greenpak4BitstreamEntity.h

+6
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ class Greenpak4NetlistEntity;
2828
#include <vector>
2929
#include <xbpar.h>
3030

31+
#include <json-c/json.h>
32+
3133
class Greenpak4EntityOutput;
3234

3335
/**
@@ -156,6 +158,7 @@ class Greenpak4BitstreamEntity
156158
virtual void PrintExtraTimingData(PTVCorner corner) const;
157159

158160
void SaveTimingData(FILE* fp, bool last);
161+
bool LoadTimingData(json_object* object);
159162

160163
protected:
161164

@@ -216,6 +219,9 @@ class Greenpak4BitstreamEntity
216219
std::map<PTVCorner, DelayMap> m_pinToPinDelays;
217220

218221
virtual void SaveTimingData(FILE* fp, PTVCorner corner);
222+
virtual bool LoadTimingDataForCorner(json_object* object);
223+
virtual bool LoadExtraTimingData(PTVCorner corner, std::string delaytype, json_object* object);
224+
bool LoadPropagationDelay(PTVCorner corner, json_object* object);
219225
};
220226

221227
#endif

0 commit comments

Comments
 (0)
Please sign in to comment.