Show gs_config.h syntax highlighted
#ifndef __gs_config_h__
#define __gs_config_h__
#include "systemc.h"
#include "protocol/generic.h"
#include "router_fabric.h"
#define TRACENAME "GS_CONFIG"
/**
* \file gs_config.h A simple config file parser for GreenBus models.
* (C) 2007 Wolfgang Klingauf @ TU Braunschweig, E.I.S.
*/
namespace tlm {
enum gs_config_parse_result {
IGNORE = 0,
MODULE,
PARAM,
BUS,
CONNECT
};
#define BUFSIZE 1024
static char line[BUFSIZE];
static char token[BUFSIZE];
typedef pair<vector<string>, gs_config_parse_result> parseresult;
/**
* Strip heading and trailing white spaces and tabs from a string.
*/
static void strip(string& str)
{
if(str.empty()) return;
int startIndex = str.find_first_not_of(" \t");
int endIndex = str.find_last_not_of(" \t");
string tmp = str;
str.erase();
str = tmp.substr(startIndex, (endIndex-startIndex+ 1) );
}
/**
* Classify a token.
* @param A token.
* @return A classification of the given token.
*/
static parseresult parse(const string &token_) {
string::size_type idx;
vector<string> tokenlist;
string token(token_);
// test for empty token --> ignore
if (token == "")
return parseresult(tokenlist, IGNORE);
// test for comment --> remove
idx = token.find("#");
if (idx != string::npos)
token = token.substr(0, idx);
// test for tabs and spaces and create token list
while((idx = token.find_first_of(" \t")) != string::npos) {
if (idx > 0) { // is a word
tokenlist.push_back(token.substr(0,idx));
}
token = token.substr(idx+1);
}
if (token.size() > 0) {
tokenlist.push_back(token);
}
if (tokenlist.empty())
return make_pair(tokenlist, IGNORE);
if (tokenlist.size() == 1)
return make_pair(tokenlist, MODULE);
else
return make_pair(tokenlist, PARAM);
}
static sc_object* getSCObject(const string &obj) {
char ch[256];
sc_simcontext *sim; // deprecated with SystemC-2.2
// TODO: enable the following line for SystemC-2.2
//const std::vector<sc_object *> &objs = sc_get_top_level_objects();
sim = sc_get_curr_simcontext(); // deprecated with SystemC-2.2
const vector<sc_object *> &objs = sim->get_child_objects();
// walk through module hierarchy
const vector<sc_object *> *childs = &objs;
string a = "", z = obj;
string::size_type idx;
while (1) {
if ((idx = z.find(".")) != string::npos) { // extract parent
a = z.substr(0,idx); // parent name without path
z = z.substr(idx+1); // reminding path to child
}
else
a = z;
bool found = false;
for (unsigned i=0; i<childs->size() && !found; i++) {
sc_object *o = (*childs)[i];
string oname(o->name());
oname = oname.substr(oname.rfind(".")+1);
if (oname == a) {
if (idx!=string::npos) { // parent found
found = true;
sc_module *m = dynamic_cast<sc_module*>(o);
childs = &(m->get_child_objects());
}
else { // obj found
return o;
}
}
}
if (!found) {
sprintf(ch, "Cannot find module [%s] in simulation context.", obj.c_str());
SC_REPORT_WARNING(TRACENAME, ch);
return NULL;
}
}
}
static sc_time_unit parse_time_unit(const string &s) {
if (s == "SC_FS") return SC_FS;
if (s == "SC_PS") return SC_PS;
if (s == "SC_NS") return SC_NS;
if (s == "SC_US") return SC_US;
if (s == "SC_MS") return SC_MS;
if (s == "SC_SEC") return SC_SEC;
return static_cast<sc_time_unit>(-1);
}
/**
* Create a bus from a vector of BUS command parameters.
* @param v: Vector{bus, clock_period, time_base}
*/
static bool gs_create_bus(busmap *m, vector<string> &v) {
char ch[256];
sc_time_unit tu = parse_time_unit(v[3]);
if (tu == -1) {
sprintf(ch, "Unknown time_unit given in BUS command!");
SC_REPORT_WARNING(TRACENAME, ch);
return false;
}
sc_time t(atoi(v[2].c_str()), tu);
// find create bus function in busmap
busmap::iterator pos = m->find(v[1]);
if (pos == m->end()) {
sprintf(ch, "Unknown bus type specified in BUS command. See router/gsrouter.h for available busses.");
SC_REPORT_WARNING(TRACENAME, ch);
return false;
}
// create the bus
sc_module_name busname(v[0].c_str());
pos->second(busname, t);
cout << "GS_CONFIG: Creating bus [" << v[0] << "] with type " << v[1] << " and clock period " << t << endl;
return true;
}
/**
* Bind greenbus ports from a vector of CONNECT command parameters.
*/
static bool gs_connect(vector<string> &v) {
unsigned p=0;
char ch[256];
while (p<v.size()) {
sc_object *iport = getSCObject(v[p++]);
sc_object *tport = getSCObject(v[p++]);
if (!iport || !tport) {
sprintf(ch, "Port binding failed. One of the specified ports does not exist.");
SC_REPORT_WARNING(TRACENAME, ch);
return false;
}
if (v.size() == 2) { // point-to-point binding
GenericMasterPort &out = *(dynamic_cast<GenericMasterPort*>(iport));
GenericTargetPort &in = *(dynamic_cast<GenericTargetPort*>(tport));
if(iport && tport) {
cout << "GS_CONFIG: Binding initiator to target: " << iport->name() << "(" << tport->name() << ")" << endl;
out(in);
}
else {
sprintf(ch, "Initiator-target port binding failed. One of the specified ports is not an tlm_port.");
SC_REPORT_WARNING(TRACENAME, ch);
return false;
}
}
else { // initiator-routers-target binding
if (p == 2) { // initiator(router)
GenericMasterPort &out = *(dynamic_cast<GenericMasterPort*>(iport));
GenericRouterTargetPort &in = *(dynamic_cast<GenericRouterTargetPort*>(tport));
if(iport && tport) {
cout << "GS_CONFIG: Binding initiator to router: " << iport->name() << "(" << tport->name() << ")" << endl;
out(in);
}
else {
sprintf(ch, "Initiator-router port binding failed. Initiator port is not tlm_port, or target port is not tlm_multi_port.");
SC_REPORT_WARNING(TRACENAME, ch);
return false;
}
}
else if (p==v.size()) { // router(target)
GenericRouterInitiatorPort &out = *(dynamic_cast<GenericRouterInitiatorPort*>(iport));
GenericTargetPort &in = *(dynamic_cast<GenericTargetPort*>(tport));
if (iport && tport) {
cout << "GS_CONFIG: Binding router to target: " << iport->name() << "(" << tport->name() << ")" << endl;
out(in);
}
else {
sprintf(ch, "Router-target port binding failed. Router port is not tlm_multi_port, or target port is not tlm_port.");
SC_REPORT_WARNING(TRACENAME, ch);
return false;
}
}
else { // router(router)
GenericRouterInitiatorPort &out = *(dynamic_cast<GenericRouterInitiatorPort*>(iport));
GenericRouterTargetPort &in = *(dynamic_cast<GenericRouterTargetPort*>(tport));
if (iport && tport) {
cout << "GS_CONFIG: Binding router to router: " << iport->name() << "(" << tport->name() << ")" << endl;
out(in);
}
else {
sprintf(ch, "Router-router port binding failed. One or both ports are not tlm_multi_port.");
SC_REPORT_WARNING(TRACENAME, ch);
return false;
}
}
}
}
return true;
}
static void executeCommand(parseresult &p) {
char ch[256];
switch (p.second) {
case CONNECT:
{
cout << "GS_CONFIG: Executing command CONNECT(";
for (unsigned i=0; i<p.first.size(); i++)
cout<<p.first[i]<<",";
cout<<")"<<endl;
if (p.first.size()%2 != 0) {
sprintf(ch, "CONNECT command must have even number of parameters.");
SC_REPORT_WARNING(TRACENAME, ch);
return;
}
gs_connect(p.first);
}
break;
case BUS:
{
cout << "GS_CONFIG: Executing command BUS(";
for (unsigned i=0; i<p.first.size(); i++)
cout<<p.first[i]<<",";
cout<<")"<<endl;
// create busmap (see router/gsrouter.h)
static busmap *m_busmap = NULL;
if (m_busmap == NULL)
m_busmap = create_busmap();
if (p.first.size() != 4) {
sprintf(ch, "BUS command must have four parameters: BUS(module_name, bus_type, clock_period, time_base)");
SC_REPORT_WARNING(TRACENAME, ch);
return;
}
gs_create_bus(m_busmap, p.first);
}
break;
default:
SC_REPORT_WARNING(TRACENAME, "Command not implemented");
}
}
/**
* Configure module parameters and create communication architecture
* from a config file.
*/
void gs_config(const char *filename) {
unsigned ln = 0;
sc_module *current_module = NULL;
char ch[256];
ifstream is(filename);
if (!is) {
SC_REPORT_ERROR("GS_CONFIG", "Cannot open config file");
return;
}
cout << endl << "GS_CONFIG: Reading configuration from file " << filename << endl;
// get simulation context
sc_simcontext *sim; // deprecated with SystemC-2.2
sim = sc_get_curr_simcontext(); // deprecated with SystemC-2.2
const vector<sc_object *> &objs = sim->get_child_objects();
// TODO: enable the following line for SystemC-2.2
//const std::vector<sc_object *> &objs = sc_get_top_level_objects();
// TODO: HACK warning --- the following code is quick and dirty.
// There should be better ways to implement the config file parser.
while(is) {
is.getline(line, BUFSIZE, '\n');
ln++;
string::size_type lidx;
string lstr(line);
if ((lidx = lstr.find("#")) != string::npos) // remove comment
lstr = lstr.substr(0, lidx);
stringstream s(lstr);
current_module = NULL; // reset
// command?
parseresult p;
p.second = IGNORE;
if (lstr.find("CONNECT") != string::npos) p.second = CONNECT;
else if (lstr.find("BUS") != string::npos) p.second = BUS;
if (p.second != IGNORE) { // command found
if ((lidx = lstr.find("(")) == string::npos || lstr.find(")") == string::npos) {
sprintf(ch, "In config file line %d: '(' or ')' missing in command", ln);
SC_REPORT_WARNING(TRACENAME, ch);
}
else { // get parameters
lstr = lstr.substr(lidx+1);
while ((lidx = lstr.find_first_of(" \t,)")) != string::npos) {
if (lidx>0 && lstr[0]!=' ' && lstr[0]!='\t') {
p.first.push_back(lstr.substr(0,lidx));
//cout << "found command parameter " << lstr.substr(0,lidx) << endl;
}
lstr = lstr.substr(lidx+1);
}
if (p.first.size() < 2) {
sprintf(ch, "In config file line %d: Too few arguments to command", ln);
SC_REPORT_WARNING(TRACENAME, ch);
}
else
executeCommand(p);
}
}
else {
// param
while(s) {
s.getline(token, BUFSIZE, '.');
if (token != "") {
parseresult p = parse(token);
switch(p.second) {
case PARAM: // set param value
if (current_module) {
cout << "GS_CONFIG: Configuring value of param [" << p.first[0] << "] in module [" << current_module->name() << "] to [" << p.first[1] << "]" << endl;
gs_configurable *gsc = dynamic_cast<gs_configurable*>(current_module);
if (gsc)
gsc->setParam(p.first[0], p.first[1]);
else {
sprintf(ch, "In config file line %d: Module [%s] is not of type gs_configurable!", ln, current_module->name());
SC_REPORT_WARNING(TRACENAME, ch);
}
}
else {
sprintf(ch, "In config file line %d: No module specified for param [%s].", ln, p.first[0].c_str());
SC_REPORT_WARNING(TRACENAME, ch);
}
break;
case MODULE: // step down in module hierarchy
{
const vector<sc_object *> *childs;
if (current_module)
childs = &(current_module->get_child_objects());
else
childs = &objs;
sc_object *o;
bool found = false;
for (unsigned int i=0; i<childs->size() && !found; i++) {
o = (*childs)[i];
string s(o->name());
s = s.substr(s.rfind(".")+1);
if (s == p.first[0]) {
/*
if (current_module)
cout << "GS_CONFIG: Found matching child of [" << current_module->name() << "] with name [" << p.first[0] << "]" << endl;
else
cout << "GS_CONFIG: Found matching root module with name [" << p.first[0] << "]" << endl;
*/
current_module = dynamic_cast<sc_module*>(o);
found = true;
}
}
if (!found) {
sprintf(ch, "In config file line %d: Module %s not found in module hierarchy.", ln, p.first[0].c_str());
SC_REPORT_WARNING(TRACENAME, ch);
}
}
break;
case IGNORE:
break;
default:
sprintf(ch, "In config file line %d: Unknown token [%s]\n", ln, token);
SC_REPORT_WARNING(TRACENAME, ch);
}
}
}
}
}
}
} // namespace tlm
#endif
See more files for this project here