Merge pull request #3216 from YosysHQ/claire/simstuff

Co-simulation improvements and fixes
This commit is contained in:
Miodrag Milanović 2022-02-28 08:19:54 +01:00 committed by GitHub
commit ec4af6af2f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 64 additions and 42 deletions

View File

@ -184,6 +184,7 @@ void FstData::reconstructAllAtTimes(std::vector<fstHandle> &signal, uint64_t sta
fstReaderSetUnlimitedTimeRange(ctx); fstReaderSetUnlimitedTimeRange(ctx);
fstReaderSetFacProcessMaskAll(ctx); fstReaderSetFacProcessMaskAll(ctx);
fstReaderIterBlocks2(ctx, reconstruct_clb_attimes, reconstruct_clb_varlen_attimes, this, nullptr); fstReaderIterBlocks2(ctx, reconstruct_clb_attimes, reconstruct_clb_varlen_attimes, this, nullptr);
past_data = last_data;
callback(last_time); callback(last_time);
if (last_time!=end_time) if (last_time!=end_time)
callback(end_time); callback(end_time);

View File

@ -801,14 +801,15 @@ struct SimInstance
child.second->setInitState(); child.second->setInitState();
} }
void setState(std::vector<std::pair<SigBit,bool>> bits, std::string values) void setState(dict<int, std::pair<SigBit,bool>> bits, std::string values)
{ {
for(size_t i=0;i<bits.size();i++) { for(auto bit : bits) {
switch(values.at(i)) { if (bit.first >= GetSize(values))
case '0' : set_state(bits.at(i).first,bits.at(i).second ? State::S1 : State::S0); break; log_error("Too few input data bits in file.\n");
case '1' : set_state(bits.at(i).first,bits.at(i).second ? State::S0 : State::S1); break; switch(values.at(bit.first)) {
default: case '0': set_state(bit.second.first, bit.second.second ? State::S1 : State::S0); break;
set_state(bits.at(i).first,State::Sx); break; case '1': set_state(bit.second.first, bit.second.second ? State::S0 : State::S1); break;
default: set_state(bit.second.first, State::Sx); break;
} }
} }
} }
@ -1124,9 +1125,10 @@ struct SimWorker : SimShared
try { try {
fst->reconstructAllAtTimes(fst_clock, startCount, stopCount, [&](uint64_t time) { fst->reconstructAllAtTimes(fst_clock, startCount, stopCount, [&](uint64_t time) {
log("Co-simulating %s %d [%lu%s].\n", (all_samples ? "sample" : "cycle"), cycle, (unsigned long)time, fst->getTimescaleString()); log("Co-simulating %s %d [%lu%s].\n", (all_samples ? "sample" : "cycle"), cycle, (unsigned long)time, fst->getTimescaleString());
bool did_something = false;
for(auto &item : inputs) { for(auto &item : inputs) {
std::string v = fst->valueOf(item.second); std::string v = fst->valueOf(item.second);
top->set_state(item.first, Const::from_string(v)); did_something |= top->set_state(item.first, Const::from_string(v));
} }
if (initial) { if (initial) {
@ -1134,8 +1136,9 @@ struct SimWorker : SimShared
write_output_header(); write_output_header();
initial = false; initial = false;
} }
update(); if (did_something)
write_output_step(5*cycle); update();
write_output_step(time);
bool status = top->checkSignals(); bool status = top->checkSignals();
if (status) if (status)
@ -1151,7 +1154,6 @@ struct SimWorker : SimShared
} catch(fst_end_of_data_exception) { } catch(fst_end_of_data_exception) {
// end of data detected // end of data detected
} }
write_output_step(5*(cycle-1)+2);
write_output_end(); write_output_end();
if (writeback) { if (writeback) {
@ -1166,8 +1168,7 @@ struct SimWorker : SimShared
std::ifstream mf(map_filename); std::ifstream mf(map_filename);
std::string type, symbol; std::string type, symbol;
int variable, index; int variable, index;
std::vector<std::pair<SigBit,bool>> inputs; dict<int, std::pair<SigBit,bool>> inputs, inits, latches;
std::vector<std::pair<SigBit,bool>> latches;
while (mf >> type >> variable >> index >> symbol) { while (mf >> type >> variable >> index >> symbol) {
RTLIL::IdString escaped_s = RTLIL::escape_id(symbol); RTLIL::IdString escaped_s = RTLIL::escape_id(symbol);
Wire *w = topmod->wire(escaped_s); Wire *w = topmod->wire(escaped_s);
@ -1176,11 +1177,13 @@ struct SimWorker : SimShared
if (index < w->start_offset || index > w->start_offset + w->width) if (index < w->start_offset || index > w->start_offset + w->width)
log_error("Index %d for wire %s is out of range\n", index, log_signal(w)); log_error("Index %d for wire %s is out of range\n", index, log_signal(w));
if (type == "input") { if (type == "input") {
inputs.emplace_back(SigBit(w,index),false); inputs[variable] = {SigBit(w,index), false};
} else if (type == "init") {
inits[variable] = {SigBit(w,index), false};
} else if (type == "latch") { } else if (type == "latch") {
latches.emplace_back(SigBit(w,index),false); latches[variable] = {SigBit(w,index), false};
} else if (type == "invlatch") { } else if (type == "invlatch") {
latches.emplace_back(SigBit(w,index),true); latches[variable] = {SigBit(w,index), true};
} }
} }
@ -1189,7 +1192,8 @@ struct SimWorker : SimShared
if (f.fail() || GetSize(sim_filename) == 0) if (f.fail() || GetSize(sim_filename) == 0)
log_error("Can not open file `%s`\n", sim_filename.c_str()); log_error("Can not open file `%s`\n", sim_filename.c_str());
bool init = true; int state = 0;
std::string status;
int cycle = 0; int cycle = 0;
top = new SimInstance(this, scope, topmod); top = new SimInstance(this, scope, topmod);
while (!f.eof()) while (!f.eof())
@ -1197,33 +1201,50 @@ struct SimWorker : SimShared
std::string line; std::string line;
std::getline(f, line); std::getline(f, line);
if (line.size()==0 || line[0]=='#') continue; if (line.size()==0 || line[0]=='#') continue;
if (init) { if (line[0]=='.') break;
if (line.size()!=latches.size()) if (state==0 && line.size()!=1) {
log_error("Wrong number of initialization bits in file.\n"); // old format detected, latch data
state = 2;
}
if (state==1 && line[0]!='b' && line[0]!='c') {
write_output_header(); write_output_header();
top->setState(latches, line); // was old format but with 1 bit latch
init = false; top->setState(latches, status);
} else { state = 3;
log("Simulating cycle %d.\n", cycle); }
if (line.size()!=inputs.size())
log_error("Wrong number of input data bits in file.\n"); switch(state)
top->setState(inputs, line); {
if (cycle) { case 0:
set_inports(clock, State::S1); status = line;
set_inports(clockn, State::S0); state = 1;
} else { break;
set_inports(clock, State::S0); case 1:
set_inports(clockn, State::S1); state = 2;
} break;
update(); case 2:
write_output_step(10*cycle); write_output_header();
if (cycle) { top->setState(latches, line);
set_inports(clock, State::S0); break;
set_inports(clockn, State::S1); default:
if (cycle) {
set_inports(clock, State::S1);
set_inports(clockn, State::S0);
} else {
top->setState(inits, line);
set_inports(clock, State::S0);
set_inports(clockn, State::S1);
}
update(); update();
write_output_step(10*cycle + 5); write_output_step(10*cycle);
} if (cycle) {
cycle++; set_inports(clock, State::S0);
set_inports(clockn, State::S1);
update();
write_output_step(10*cycle + 5);
}
cycle++;
break;
} }
} }
write_output_step(10*cycle); write_output_step(10*cycle);